Entity framework 5 实体框架代码优先关系使用fluent API转换为字符串

Entity framework 5 实体框架代码优先关系使用fluent API转换为字符串,entity-framework-5,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 protec

我有以下课程

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

    ...
}
现在我把一些数据放在表中

地址类型记录 我在业务中输入的类型名称

在地址记录中 地址类型\我在业务中输入的类型名称

当我在这个平台上运行单元测试时,我希望能回到我的记录中

List<Address> addresses = context.Addresses.ToList()
Assert.AreEqual(addresses[0].AddressType.TypeName, "Business");
List addresses=context.addresses.ToList()
Assert.AreEqual(地址[0].AddressType.TypeName,“业务”);
但这无法告诉我AddressType为null


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

要加载相关实体,您必须告诉它Entity Framework,方法是使用“快速加载”:

使用System.Data.Entity;
//...
var addresses=context.addresses.Include(a=>a.AddressType).ToList()
…或通过延迟加载,如果您将导航属性标记为“虚拟”,则默认情况下会启用延迟加载:

公共虚拟地址类型地址类型{get;set;}
即时加载在单个数据库往返中将父数据和相关数据一起加载。延迟加载需要两次往返,第二次在您访问行
地址[0].AddressType.TypeName
中的导航属性时发生在convers下

编辑

测试项目以显示本例中的延迟加载有效(EF5.0、.NET4.0、SQLServerExpress2008R2作为数据库)。我只把
virtual
放在
AddressType
前面。其余部分与您的型号相同:

使用系统;
使用System.Collections.Generic;
使用System.ComponentModel.DataAnnotations.Schema;
使用System.Data.Entity;
使用System.Linq;
命名空间EFLazyLoading
{
公共部分类地址
{
公共Guid地址ID{get;set;}
公共虚拟地址类型地址类型{get;set;}
}
公共部分类AddressType
{
公共字符串类型名{get;set;}
}
公共类MyContext:DbContext
{
公共数据库集地址{get;set;}
公共数据库集地址类型{get;set;}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity().HasKey(p=>p.AddressID);
modelBuilder.Entity().Property(p=>p.AddressID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity().HasRequired(p=>p.AddressType);
modelBuilder.Entity().HasKey(p=>p.TypeName);
}
}
班级计划
{
静态void Main(字符串[]参数)
{
SetInitializer(新的DropCreateDatabaseAlways());
使用(var ctx=new MyContext())
{
var地址=新地址
{
AddressType=新的AddressType{TypeName=“业务”}
};
ctx.地址.添加(地址);
ctx.SaveChanges();
}
使用(var ctx=new MyContext())
{
列表地址=ctx.addresses.ToList();
字符串typeName=地址[0]。AddressType.typeName;
}
}
}
}
最后一行的
typeName
结果与预期一致:


这两个都不适合我。Include in not part of IQueryable是第一个错误,第二个错误的AddessType仍然为null。我想这与我在OnModelCreating中创建键的方式有关。@MarkToth:
OnModelCreating
在我看来很好。您是否使用System.Data.Entity设置了
在代码文件的开头?它需要具有可用的
Include
。第二个问题:您是否为您的上下文设置了
ProxyCreationEnabled=false
LazyLoadingEnabled=false
?我还是想使用延迟加载,因此第一个解决方案并不是我真正想要的,因为我并不总是需要知道地址的类型。我不想在我的存储库模式中使用include,除非这是绝对必要的。我认为这是因为AddressTypes中的键不是按常规命名的,即AddressTypeID,但我也不希望AddressType中有ID键,因为它是冗余的,因为TypeName字段是唯一的。这有意义吗?我的应用程序应该更具体地说明我正在使用的存储库模式。@MarkToth:键名不是常规的,但是您可以使用
HasKey(p=>p.TypeName)
正确地覆盖约定。我看这里没有问题。为什么惰性加载不起作用?您是否检查了
context.Configuration.ProxyCreationEnabled
context.Configuration.LazyLoadingEnabled
设置?它们必须都是
true
@MarkToth:没关系
AddressType
不应是动态代理。但是我刚才看到您在问题中说,
AddressType
表中的PK
TypeName
是一个
uniqueidentifier
(=Guid)。这是不对的。它必须是一个
nvarchar
,就像
地址中的FK一样。
List<Address> addresses = context.Addresses.ToList()
Assert.AreEqual(addresses[0].AddressType.TypeName, "Business");