Handling complex key maps

In this recipe, we use complex keys to map objects that cannot be keyed with a single property.

Getting ready

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.

How to do it...

Let us get connected to the database using the following steps:

  1. We start by adding a new unit test named 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);
        }
      }
    }
  2. Add a new C# class named 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();
        }
      }
    }
  3. Add a new C# class named 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; }
      }
    }
  4. Now that we have our domain objects, we want to add a 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");
        }
      }
    }
  5. Modify 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();
      }
    }
  6. Run our test, and see how it works.

How it works...

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.

There's more...

Keys are used for relationships

While using a complex or composite key, be aware that it is going to be used for your related objects as well, and you will need to use the Map() method on one-to-many and many-to-many collections, to define that constraint.

See also

In this chapter:

  • Creating one-to-many maps
  • Creating many-to-many maps
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset