Creating Edmx files and testing

The favorite ORM in .NET world for me it is edmx files. It gives you the database plain – and have generators for POCO (http://blogs.msdn.com/b/adonet/archive/2010/01/25/walkthrough-poco-template-for-the-entity-framework.aspx) as for EF4.1 DBContext(http://blogs.msdn.com/b/adonet/archive/2011/03/15/ef-4-1-model-amp-database-first-walkthrough.aspx).

I will use this one – because of the new ! But the template is over simplistic  -so I improved . I do not want you to bother you with my experience – I want to say that, after playing with Data attributes – I decide that Fluent Configuration suits all. The template is here:

DBContext-SecondVersion.zip

 

For example, the default template

Also for testing I use the fact the default EF4.1  Model1.Context.tt generates this code:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }

( see playing on safe side to NOT drop the existing database?!)

Mine Model1.Context.tt generates this:


 protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
    		var prefix = System.Configuration.ConfigurationManager.AppSettings["prefixTable"]??"";
    		bool Continue=true;
            OnBeginModelCreating(modelBuilder,prefix, ref Continue);
    		if(!Continue)
    			return;
    
    		//construct default
    		#region smsg_Message 
    		modelBuilder.Entity<smsg_Message>().ToTable(prefix  + "smsg_Message");
    		modelBuilder.Entity<smsg_Message>().HasKey(item => item.IDMessage);
    
    
    		#endregion
    		#region smsg_Message_Archive 
    		modelBuilder.Entity<smsg_Message_Archive>().ToTable(prefix  + "smsg_Message_Archive");
    		modelBuilder.Entity<smsg_Message_Archive>().HasKey(item => item.IDMessageArchive);
    
    
    		#endregion
    		#region smsg_MessageThread 
    		modelBuilder.Entity<smsg_MessageThread>().ToTable(prefix  + "smsg_MessageThread");
    		modelBuilder.Entity<smsg_MessageThread>().HasKey(item => item.IDMessageThread);
    
    		modelBuilder.Entity<smsg_MessageThread>()
                    .HasRequired(item => item.IDMessage_IDMessageInitial)
                    .WithMany(u => u.IDMessage_IDMessageInitial)
                    .HasForeignKey(x => x.IDMessageInitial)
                    .WillCascadeOnDelete(false);
    
    		
    		modelBuilder.Entity<smsg_MessageThread>()
                    .HasRequired(item => item.IDMessage_IDMessageReply)
                    .WithMany(u => u.IDMessage_IDMessageReply)
                    .HasForeignKey(x => x.IDMessageReply)
                    .WillCascadeOnDelete(false);
    
    		
    		modelBuilder.Entity<smsg_MessageThread>()
                    .HasRequired(item => item.IDMessageArchive_IDMessageInitial)
                    .WithMany(u => u.IDMessageArchive_IDMessageInitial)
                    .HasForeignKey(x => x.IDMessageInitial)
                    .WillCascadeOnDelete(false);
    
    		
    		modelBuilder.Entity<smsg_MessageThread>()
                    .HasRequired(item => item.IDMessageArchive_IDMessageReply)
                    .WithMany(u => u.IDMessageArchive_IDMessageReply)
                    .HasForeignKey(x => x.IDMessageReply)
                    .WillCascadeOnDelete(false);
    
    		
    
    		#endregion
    	
    		OnFinishModelCreating(modelBuilder, prefix);
    		
        }

More, for giving you a smell of what the templates generates, look at this function for reading messages sent:


 public  IEnumerable<IUserMessage<IUser<String>,string>> RetrieveMessageSent(DateTime dt)
        {
            using (smsg_Message_List ml = new smsg_Message_List(ConnectionMessaging))
            {
                ml.LoadFromDB.AddToCustomPredicate(smsg_Message_FindDB.fexp_FromUser(this.Key));
                ml.LoadFromDB.AddToCustomPredicate(smsg_Message_FindDB.fexp_DateInsertedBetweenEqDate(dt, dt));
                ml.LoadFromDB.LoadFindCustomPredicate();
                return ml;
            }
        }

The class smsg_Message_List and the AddToCustomPredicate , LoadFindCustomPredicate and the expression fexp_FromUser and fexp_DateInsertedBetweenEqDate are automatically generated by the template.
I do not think that the template is perfect – it just helps me a lot!

For the database tests, I was thinking of NUnit – but was deprecated by xUnit. It has a nice project, named SpecificationExample – and it generates data in BDD style .
For example, this code:


 public void CreateUsersAndSendMessage()
        {
            
            List<SimpleUser> users = null;

            "When create two users".Context(() => users = CreateUsersAndDeleteItFirst());
            "it will be friends".Assert(() => FindFriend(users).ShouldNotBeNull());
            
            "and when send message from first user to second user".Do(() => SendMessage(users));

            
            "we will retrieve it searching message from first user ".Assert(() => RetrieveMessageSent( users[0]).ShouldEqual(1));

            "we will NOT retrieve it searching message from second user".Assert(() => RetrieveMessageSent(users[1]).ShouldEqual(0));

            "we will retrieve searching messages received by second user".Assert(() => RetrieveMessageReceived(users[1]).ShouldEqual(1));

            "we will retrieve count of unread messages :1 ".Assert(() => RetrieveMessageUnreadCount(users[1]).ShouldEqual(1));

            


        }

run by this command:

xunit.console.clr4.x86.exe "$(TargetPath)" /html "$(TargetDir)a.html" 

in Build events it will generate the following HTML


————————————————————————

✔  When create two users and when send message from first user to second user, it will be friends

Output
Before : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage
After : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage

0.060s

✔  When create two users and when send message from first user to second user, we will NOT retrieve it searching message from second user

Output
Before : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage
After : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage

0.099s

✔  When create two users and when send message from first user to second user, we will retrieve count of unread messages :1

Output
Before : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage
After : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage

0.032s

✔  When create two users and when send message from first user to second user, we will retrieve it searching message from first user

Output
Before : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage
After : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage

0.053s

✔  When create two users and when send message from first user to second user, we will retrieve searching messages received by second user

Output
Before : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage
After : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage

—————————————–


Nice , isn’t it?

Homework :
1. use the ITLIst.tt template , search for

//TODO: prefix

and make generating same prefix for the table as in the Model1.Context.tt( search prefix)
( Do not forget the change the edmx file name in the .tt file!)
2. Make a .t4 file to share commonalities( such as edmx name)