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:
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)