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

Jat*_*tin 15 entity-framework ef-code-first entity-framework-4.1

我跟随两个实体,我试图使用外键关联(一对一).

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; }
}
Run Code Online (Sandbox Code Playgroud)

这会抛出ModelValidationException.任何想法为什么这样一个看似简单的一对一双向关系无法配置.

编辑:

这是例外:

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

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

Source = EntityFramework StackTrace:位于System.Data.Entity的System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateCsdl(EdmModel model)的System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateAndSerializeCsdl(EdmModel model,XmlWriter writer) .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.Linq.Enumerable.ToList的System.Data.Entity.Internal.Linq.InternalSet 1.GetEnumerator() at System.Data.Entity.Infrastructure.DbQuery1.System.Collections.Generic.IEnumerable.GetEnumerator()at System.Collections.Generic.List 1..ctor(IEnumerable1 collection) [TSource](IEnumerable`1 source)位于D:\ RailwayProjects\RelayAnalysis\TestApplication\MainWindow.xaml.cs中的TestApplication.MainWindow.Window_Loaded(Object sender,RoutedEventArgs e):第33行InnerException:

Sla*_*uma 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; }
}
Run Code Online (Sandbox Code Playgroud)

Fluent API中的映射:

modelBuilder.Entity<StandardRack>()
    .HasOptional(rack => rack.StandardRelay)
    .WithRequired(relay => relay.StandardRack);
Run Code Online (Sandbox Code Playgroud)

(我在这里假设StandardRack有一个可选的继电器.)

  • @MichaelEdenfield:如果双方都是可选的或两者都是必需的,你只需要(并且只有选项)选择`With ... Principal`.如果一方是可选的,一方是必需的,你就不能选择它,因为那时可选方总是本金.`HasOptional(...).WithRequired(...)`或`HasRequired(...).WithOptional(...)`是唯一有效的组合.如果他想要一个可选的必需关系,问题并不明显,我只是在我的答案中假设.对于必需的关系,映射会有所不同(但仍然没有FK属性). (3认同)
  • 另外,请注意:为了使用延迟加载,您应该将`virtual`添加到非基本属性. (2认同)

Ari*_*ini 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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Sud*_*SMD 8

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

请注意,FK未在Enitity中明确定义,但它是使用流畅的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")));
Run Code Online (Sandbox Code Playgroud)

流畅的API将加列StandardRack_IdStandardRelay.

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