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 ;
#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)