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:

1
2
3
4
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:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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:

01
02
03
04
05
06
07
08
09
10
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:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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)