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.RetryLazy
2.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.InternalSet
1.GetEnumerator()中
位于System.Data.Entity.Infrastructure.DbQuery
1.System.Collections.Generic.IEnumerable.GetEnumerator() 位于System.Collections.Generic.List
1..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")));