15

我有以下两个我试图使用外键关联关联(一对一)的实体。

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: : 多重性在关系“StandardRelay_StandardRack”中的角色“StandardRelay_StandardRack_Source”中无效。因为从属角色属性不是关键属性,所以从属角色的多重性的上限必须是“*”。

Source=EntityFramework StackTrace:在 System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateCsdl(EdmModel model, XmlWriter writer) 在 System.Data.Entity.Edm.EdmModelExtensions.ValidateAndSerializeCsdl(EdmModel model) .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.InternalSet1.Initialize() 在 System.Data.Entity.Internal.Linq.InternalSet1.GetEnumerator() at System.Data.Entity.Infrastructure.DbQuery1.System.Collections.Generic.IEnumerable.GetEnumerator() 在 System.Collections.Generic.List 1..ctor(IEnumerable1 集合) 在 System.Linq.Enumerable.ToList[TSource](IEnumerable`1 源) 在 TestApplication.MainWindow.Window_Loaded(Object sender , RoutedEventArgs e) 在 D:\RailwayProjects\RelayAnalysis\TestApplication\MainWindow.xaml.cs:line 33 InnerException:

4

4 回答 4

30

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

(我在这里假设 aStandardRack有一个可选的中继。)

于 2012-04-11T14:58:25.310 回答
9

Here is how you can specify one-to-one relationship with FK using fluent api.

Note that FK is not explicitly defined in Enitity, but it's defined using 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")));

fluent api will add column StandardRack_Id in StandardRelay.

Note that method name WithOptionalPrincipal() is quite ironic. msdn documentation of WithOptionalDependent shall make it clear.

于 2016-07-14T06:53:51.463 回答
8

我认为foreignKey应该是Id,而不是StandardRack_id。此外,您应该使用虚拟,以便能够使用延迟加载。

This works for me

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();
        }
    }
}
于 2012-04-11T15:02:14.577 回答
0

You might want to adapt the annotation of ID in StandardRelay. Also see this related question:

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;}
}
于 2016-05-20T07:59:02.007 回答