Entity framework 实体框架代码优先:使用注释设置一对一外键关联
我尝试使用外键关联(一对一)关联以下两个实体Entity framework 实体框架代码优先:使用注释设置一对一外键关联,entity-framework,entity-framework-4.1,ef-code-first,Entity Framework,Entity Framework 4.1,Ef Code First,我尝试使用外键关联(一对一)关联以下两个实体 public class StandardRack { public int Id {get;set} public StandardRelay StandardRelay {get;set} } public class StandardRelay { public int Id {get;set} public int StandardRack_Id {get;set;} [Required][Fo
public class StandardRack {
public int Id {get;set}
public StandardRelay StandardRelay {get;set}
}
public class StandardRelay {
public int Id {get;set}
public int StandardRack_Id {get;set;}
[Required][ForeignKey("StandardRack_Id")]
public StandardRack StandardRack { get; set; }
}
这会引发ModelValidationException。你知道为什么这样一个看似简单的一对一的双向关系无法配置吗
编辑:
例外情况如下:
捕获到System.Data.Entity.ModelConfiguration.ModelValidationException
消息=在模型生成过程中检测到一个或多个验证错误:
System.Data.Edm.EdmAssociationId::多重性在关系“StandardRelay\u StandardRack”中的角色“StandardRelay\u StandardRack\u Source”中无效。因为依赖角色属性不是键属性,所以依赖角色的多重性上限必须为�*�.
Source=EntityFramework
堆栈跟踪:
位于System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateAndSerializeCsdl(EdmModel模型,XmlWriter)
位于System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateCsdl(EdmModel模型)
位于System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest,DbProviderInfo providerInfo)
位于System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
位于System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
在System.Data.Entity.Internal.RetryLazy2.GetValue(TInput输入)
在System.Data.Entity.Internal.LazyInternalContext.InitializeContext()中
位于System.Data.Entity.Internal.InternalContext.Initialize()处
位于System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(类型entityType)
在System.Data.Entity.Internal.Linq.InternalSet中
1.Initialize()
在System.Data.Entity.Internal.Linq.InternalSet1.GetEnumerator()中
位于System.Data.Entity.Infrastructure.DbQuery
1.System.Collections.Generic.IEnumerable.GetEnumerator()
位于System.Collections.Generic.List1..ctor(IEnumerable
1集合)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
在D:\RailwayProjects\RelayAnalysis\TestApplication\MainWindow.xaml.cs:第33行中加载了TestApplication.MainWindow.Window(对象发送器,RoutedEventArgs e)
内部异常:
Entitiy Framework不支持一对一外键关联。您必须删除外键并使用共享主键(依赖项的主键同时是其主体的外键): Fluent API中的映射:
modelBuilder.Entity<StandardRack>()
.HasOptional(rack => rack.StandardRelay)
.WithRequired(relay => relay.StandardRack);
modelBuilder.Entity()
.has可选(rack=>rack.StandardRelay)
.需要时(继电器=>继电器.标准机架);
(我在这里假设一个
StandardRack
有一个可选的继电器。)我认为外键应该是Id,而不是StandardRack\u Id。
另外,为了能够使用延迟加载,您应该使用虚拟
这对我有用
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
namespace Racks
{
public class StandardRack
{
public int Id { get; set; }
public virtual StandardRelay StandardRelay { get; set; }
}
public class StandardRelay
{
public int Id { get; set; }
public int StandardRack_Id { get; set; }
[ForeignKey("Id")]
[Required]
public virtual StandardRack StandardRack { get; set; }
}
public class Context : DbContext
{
static Context()
{
Database.SetInitializer<Context>(null);
}
public DbSet<StandardRack> StandardRacks { get; set; }
public DbSet<StandardRelay> StandardRelays { get; set; }
}
class Program
{
static void Main(string[] args)
{
var context = new Context();
context.Database.Delete();
context.Database.Create();
var standardRack = new StandardRack();
standardRack.StandardRelay = new StandardRelay();
context.StandardRacks.Add(standardRack);
context.SaveChanges();
}
}
}
使用System.ComponentModel.DataAnnotations;
使用System.Data.Entity;
命名空间机架
{
公共类标准框架
{
公共int Id{get;set;}
公共虚拟标准中继标准中继{get;set;}
}
公共级标准继电器
{
公共int Id{get;set;}
public int StandardRack_Id{get;set;}
[外国钥匙(“Id”)]
[必需]
公共虚拟StandardRack StandardRack{get;set;}
}
公共类上下文:DbContext
{
静态上下文()
{
Database.SetInitializer(null);
}
公共数据库集标准框架{get;set;}
公共数据库集{get;set;}
}
班级计划
{
静态void Main(字符串[]参数)
{
var context=新上下文();
context.Database.Delete();
context.Database.Create();
var standardRack=新的standardRack();
standardRack.StandardRelay=新的StandardRelay();
context.standardRack.Add(standardRack);
SaveChanges();
}
}
}
您可能需要调整StandardRelay中ID的注释。另见此相关问题:
下面是如何使用fluent api指定与FK的一对一关系
public class StandardRack {
public int Id {get;set}
public StandardRelay StandardRelay {get;set}
}
public class StandardRelay {
public int Id {get;set}
public StandardRack StandardRack { get; set; }
}
modelBuilder.Entity<StandardRack>()
.HasOptional(x => x.StandardRelay)
.WithOptionalPrincipal(y => y.StandardRack)
.Map(configurationAction: new Action<ForeignKeyAssociationMappingConfiguration>(x => x.MapKey("StandardRack_Id")));
请注意,FK并没有在ENITY中明确定义,但它是使用fluent api定义的
public class StandardRack {
public int Id {get;set}
public StandardRelay StandardRelay {get;set}
}
public class StandardRelay {
public int Id {get;set}
public StandardRack StandardRack { get; set; }
}
modelBuilder.Entity<StandardRack>()
.HasOptional(x => x.StandardRelay)
.WithOptionalPrincipal(y => y.StandardRack)
.Map(configurationAction: new Action<ForeignKeyAssociationMappingConfiguration>(x => x.MapKey("StandardRack_Id")));
公共类标准框架{
公共int Id{get;set}
公共标准中继标准中继{get;set}
}
公共级标准继电器{
公共int Id{get;set}
公共StandardRack StandardRack{get;set;}
}
modelBuilder.Entity()
.has可选(x=>x.StandardRelay)
.带有可选主体(y=>y.StandardRack)
.Map(配置操作:新操作(x=>x.MapKey(“StandardRack_Id”));
fluent api将在StandardRelay
中添加列StandardRack\u Id
注意,方法名()非常讽刺。的msdn文档应明确说明。您能否发布
ModelValidationException
的详细信息,包括可能的内部异常?请参阅我对exceptionArialdo的编辑@Slauma,您和我建议的方法会导致相同的数据库结构,即,StandardRack的Id列用作StandardRelay外键(Id)的目标。我将采用阿里亚尔多的方法,并将他的答案标记为正确,尽管两个答案都有效。+1好主意!我没想到一对一映射也可以用于注释。我想知道如果您完全删除[ForeignKey]
属性(但保留[Required]
属性),它是否也可以工作。你测试过了吗?@Slauma,即使我删除了Foreignkey,它也会工作,并创建相同的数据库结构。所以Foreignkey可以省略
public class StandardRack {
public int Id {get;set}
public StandardRelay StandardRelay {get;set}
}
public class StandardRelay {
public int Id {get;set}
public StandardRack StandardRack { get; set; }
}
modelBuilder.Entity<StandardRack>()
.HasOptional(x => x.StandardRelay)
.WithOptionalPrincipal(y => y.StandardRack)
.Map(configurationAction: new Action<ForeignKeyAssociationMappingConfiguration>(x => x.MapKey("StandardRack_Id")));