实体框架代码优先:使用注释设置一对一外键关联

时间:2012-04-11 14:37:58

标签: 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][ForeignKey("StandardRack_Id")]
    public StandardRack StandardRack { get; set; }
}

抛出ModelValidationException。任何想法为何无法配置这种看似简单的一对一双向关系。

修改

以下是例外:

  

捕获了System.Data.Entity.ModelConfiguration.ModelValidationException         消息=在模型生成期间检测到一个或多个验证错误:

     

System.Data.Edm.EdmAssociationEnd :: Multiplicity在Role' StandardRelay_StandardRack_Source'中无效。在关系' StandardRelay_StandardRack'。由于Dependent Role属性不是关键属性,因此Dependent Role的多重性的上限必须为�*�。

     

源=的EntityFramework         堆栈跟踪:              在System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateAndSerializeCsdl(EdmModel model,XmlWriter writer)              在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 input) at System.Data.Entity.Internal.LazyInternalContext.InitializeContext() at System.Data.Entity.Internal.InternalContext.Initialize() at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) at System.Data.Entity.Internal.Linq.InternalSet 1.Initialize()              at System.Data.Entity.Internal.Linq.InternalSet 1.GetEnumerator() at System.Data.Entity.Infrastructure.DbQuery 1.System.Collections.Generic.IEnumerable.GetEnumerator()              在System.Collections.Generic.List 1..ctor(IEnumerable 1个集合)              在System.Linq.Enumerable.ToList [TSource](IEnumerable`1 source)              在T:\ RailwayProjects \ RelayAnalysis \ TestApplication \ MainWindow.xaml.cs中的TestApplication.MainWindow.Window_Loaded(Object sender,RoutedEventArgs e):第33行         InnerException:

4 个答案:

答案 0 :(得分:28)

Entitiy Framework不支持一对一外键关联。您必须删除外键并使用共享主键(从属的主键是它同时对主体的外键):

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

Fluent API中的映射:

modelBuilder.Entity<StandardRack>()
    .HasOptional(rack => rack.StandardRelay)
    .WithRequired(relay => relay.StandardRack);

(我在此假设StandardRack有一个可选的接力。)

答案 1 :(得分:8)

我认为foreignKey应该是Id,而不是StandardRack_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();
        }
    }
}

答案 2 :(得分:5)

以下是如何使用流畅的api指定与FK的一对一关系。

请注意,在Enitity中没有明确定义FK,但是使用流畅的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")));

流畅的api会在StandardRack_Id中添加列StandardRelay

请注意,方法名称WithOptionalPrincipal()非常具有讽刺意味。 WithOptionalDependent的msdn文档应明确说明。

答案 3 :(得分:0)

您可能希望在StandardRelay中调整ID的注释。另请参阅此相关问题:

What does principal end of an association means in 1:1 relationship in Entity framework

public class Foo
{
    public string FooId{get;set;}
    public Boo Boo{get;set;}
}

public class Boo
{
    [Key, ForeignKey("Foo")]
    public string BooId{get;set;}
    public Foo Foo{get;set;}
}