In this recipe, we use complex keys to map objects that cannot be keyed with a single property.
We will be using NuGet Package Manager to install the Entity Framework 4.1 assemblies as follows:
The package installer can be found at http://nuget.org/.
We will also be using a database for connecting to the data and updating it.
Open the Improving Complex Key Maps solution in the included source code examples.
Let us get connected to the database using the following steps:
MappingTest
to the Test
project. We will make a test that connects to the database, and retrieves an object. This will test the configuration and ensure that the model matches the database schema. Use the following code:using System; using System.Collections.Generic; using System.Linq; using System.Text; using BusinessLogic; using DataAccess; using DataAccess.Database; using Microsoft.VisualStudio.TestTools.UnitTesting; using Test.Properties; using System.Data.Entity; namespace Test { [TestClass] public class MappingTest { [TestMethod] public void ShouldReturnABlogWithAuthorDetails() { //Arrange var init = new Initializer(); var context = new BlogContext(Settings.Default.BlogConnection); init.InitializeDatabase(context); //Act var blog = context.Set<Blog>().FirstOrDefault(); //Assert Assert.IsNotNull(blog); } } }
Initializer
to the DataAccess
project in the Database
folder, with the following code:using System; using System.Collections.Generic; using System.Data.Entity; using BusinessLogic; namespace DataAccess.Database { public class Initializer : DropCreateDatabaseAlways<BlogContext> { public Initializer() { } protected override void Seed(BlogContext context) { context.Set<Blog>().Add(new Blog { Creationdate = DateTime.Now, ShortDescription = "Testing", Title = "Test Blog" }); context.SaveChanges(); } } }
Blog
to the BusinessLogic
project, with the following code:using System; namespace BusinessLogic { public class Blog { public DateTime Creationdate { get; set; } public string ShortDescription { get; set; } public string Title { get; set; } } }
Mapping
folder to the DataAccess
project and then add a BlogMapping
class to the folder, with the following code:using System.ComponentModel.DataAnnotations; using System.Data.Entity.ModelConfiguration; using BusinessLogic; namespace DataAccess.Mappings { public class BlogMapping : EntityTypeConfiguration<Blog> { public BlogMapping() { this.HasKey(x => new{x.Creationdate,x.Title}); this.Property(x => x.Title).IsRequired().HasMaxLength(250).HasColumnOrder(1); this.Property(x => x.Creationdate).HasColumnName("CreationDate").IsRequired().HasColumnOrder(0); this.Property(x => x.ShortDescription).HasColumnType("Text").IsMaxLength().IsOptional().HasColumnName("Description"); } } }
BlogContext
to include Blog DbSet<>
and the new configurations, with the following code:using System; using System.Data.Entity; using System.Linq; using BusinessLogic; using DataAccess.Mappings; namespace DataAccess { public class BlogContext : DbContext { public BlogContext(string connectionString) : base(connectionString) { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new BlogMapping()); base.OnModelCreating(modelBuilder); } public DbSet<Blog> Blogs { get; set; } public IQueryable<T> Find<T>() where T : class { return this.Set<T>(); } public void Refresh() { this.ChangeTracker.Entries().ToList().ForEach(x=>x.Reload()); } public void Commit() { this.SaveChanges(); } }
We start by defining a test that retrieves the blog object. This will be testing the key mapping for us.
The HasKey()
method accepts a lambda that allows us to map multiple properties to the key of the table. This creates a composite key that is ordered in the order that we type in the lambda. If we want to adjust this order, we can use the HasColumnIOrder()
method.
This defines a unique combination of multiple columns that make up the unique identification of a record This is normally reserved for more legacy database mappings, but we can have scenarios where we would want to create this for new databases as well.