实体框架代码首先使用流畅的API来串联关系

时间:2013-04-06 13:08:37

标签: entity-framework-5

我有以下课程

public pratial class Address
{
    public Guid AddressID{ get; set; }
    public AddressType AddressType{ get; set; }
}

public partial class AddressType
{
    public string TypeName{ get; set; }
}

在我的派生DBContext类中,我重写了OnModelCreating

protected override OnModelCreating(DBModelBuilder modelBuilder)
{
    modelBuilder.Entity<Address>().HasKey( p => p.AddressID );
    modelBuilder.Entity<Address>().Property ( p => p.AddressID)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    modelBuilder.Entity<Address>().HasRequired( p => p.AddressType);
    modelBuilder.Entity<AddrssType>().HasKey( p => p.TypeName );

    ...
}

这样可以很好地填写数据库中的记录

数据库中的我的表最终看起来像这样

Addresses Table
AddressID (PK, uniqueidentified, not null)
AddressType_TypeName(FK, nvarchar(32), not null)

AddressTypes Table
TypeName (PK, uniqueidentifies, not null)

现在我在表格中放了一些数据

AddressTypes记录 TypeName我放入了商业

地址记录中的

AddressType_TypeName我放入了商业

当我对此进行单元测试时,我希望重新参加我的记录

List<Address> addresses = context.Addresses.ToList()
Assert.AreEqual(addresses[0].AddressType.TypeName, "Business");

但是这告诉我AddressType为null

如何设置Address和AddressType之间的关系,以便找回我已经连接的AddressType?

1 个答案:

答案 0 :(得分:0)

要加载相关实体,您必须使用 eager loading 告诉它实体框架:

using System.Data.Entity;

//...

var addresses = context.Addresses.Include(a => a.AddressType).ToList()

...或延迟加载,如果您将导航属性标记为virtual,则默认启用

public virtual AddressType AddressType { get; set; }

Eager loading在单个数据库往返中将父数据和相关数据加载在一起。延迟加载需要两次往返,当您访问行addresses[0].AddressType.TypeName中的导航属性时,第二次发生在转换下。

修改

测试项目以显示此示例中的延迟加载(EF 5.0,.NET 4.0,SQL Server Express 2008 R2作为数据库)。我只将virtual放在AddressType前面。其余部分与您的模型完全相同:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;

namespace EFLazyLoading
{
    public partial class Address
    {
        public Guid AddressID{ get; set; }
        public virtual AddressType AddressType{ get; set; }
    }

    public partial class AddressType
    {
        public string TypeName{ get; set; }
    }

    public class MyContext : DbContext
    {
        public DbSet<Address> Addresses { get; set; }
        public DbSet<AddressType> AddressTypes { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Address>().HasKey( p => p.AddressID );
            modelBuilder.Entity<Address>().Property ( p => p.AddressID)
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            modelBuilder.Entity<Address>().HasRequired( p => p.AddressType);
            modelBuilder.Entity<AddressType>().HasKey( p => p.TypeName );
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>());
            using (var ctx = new MyContext())
            {
                var address = new Address
                {
                    AddressType = new AddressType { TypeName = "Business" }
                };
                ctx.Addresses.Add(address);
                ctx.SaveChanges();
            }

            using (var ctx = new MyContext())
            {
                List<Address> addresses = ctx.Addresses.ToList();

                string typeName = addresses[0].AddressType.TypeName;
            }
        }
    }
}

最后一行中typeName的结果符合预期:

Lazy loading