Entity framework EF v-Next是否支持一对一外键关联?

Entity framework EF v-Next是否支持一对一外键关联?,entity-framework,Entity Framework,我有实体A和B,我想在A和B之间创建2个不同的1-1关联。A应该扮演主体的角色。像这样: public class A { public int Id {get; set;} public B B1 {get; set;} public B B2 {get; set;} } public class B { public int Id {get; set;} } 由于EF不支持一对一外键关联,因此我无法使用EF创建工作模型/数据库。对我来说,这听起来像是一个

我有实体A和B,我想在A和B之间创建2个不同的1-1关联。A应该扮演主体的角色。像这样:

public class A 
{
    public int Id {get; set;}
    public B B1 {get; set;}
    public B B2 {get; set;}
}

public class B
{
    public int Id {get; set;}
}
由于EF不支持一对一外键关联,因此我无法使用EF创建工作模型/数据库。对我来说,这听起来像是一个严重的限制。是否有计划在即将发布的EF版本中支持此类关联

要使其正常工作,最好的解决方法是什么。我知道如何创建两个一对多关联。然而,这将使B成为主体,并给我带来级联删除的问题


谢谢你回答我的问题。下面是我想做的一个示例,即在一个实体A和另一个实体B之间创建两个(或更多)1对1关联。这是EF在vNext中可以支持的吗?或者,为什么这是一个坏主意

再次感谢, 梅里林

公共A类
{
公共int Id{get;set;}
公共int B1_Id{get;set;}
公共B1{get;set;}
公共int B2_Id{get;set;}
公共B B2{get;set;}
}
公共B级
{
公共int Id{get;set;}
}
公共类SampleContext:DbContext
{
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity().HasKey(c=>c.Id);
modelBuilder.Entity().HasKey(c=>c.Id);
modelBuilder.Entity().HasRequired(c=>c.B1).WihOptional().ForeignKey(x=>x.B1\u Id);
modelBuilder.Entity().HasRequired(c=>c.B2).WihOptional().ForeignKey(x=>x.B2\u Id);
}
}

解释您需要解决什么问题?这是EF 5.0中一对一映射的示例

class Program
{
    static void Main(string[] args)
    {
        using (var context = new SampleContext())
        {
            var mainEntity = new MainEntity();
            mainEntity.DetailEntity = new DetailEntity();

            context.SaveChanges();
        }
    }
}

public class SampleContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<MainEntity>().HasKey(c => c.Id);
        modelBuilder.Entity<DetailEntity>().HasKey(c => c.Id);

        modelBuilder.Entity<MainEntity>().HasOptional(c => c.DetailEntity).WithRequired(p => p.MainEntity);
        modelBuilder.Entity<DetailEntity>().HasRequired(c => c.MainEntity).WithOptional(p => p.DetailEntity);
    }

    public virtual DbSet<MainEntity> MainEntities { get; set; }

    public virtual DbSet<DetailEntity> DetailEntities { get; set; }
}

public class MainEntity
{
    public int Id { get; set; }

    public DetailEntity DetailEntity { get; set; }
}

public class DetailEntity
{
    public int Id { get; set; }

    public MainEntity MainEntity { get; set; }
}
类程序
{
静态void Main(字符串[]参数)
{
使用(var context=new SampleContext())
{
var maintentity=新的maintentity();
mainEntity.DetailEntity=新的DetailEntity();
SaveChanges();
}
}
}
公共类SampleContext:DbContext
{
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity().HasKey(c=>c.Id);
modelBuilder.Entity().HasKey(c=>c.Id);
modelBuilder.Entity().HasOptional(c=>c.DetailEntity)。WithRequired(p=>p.MainEntity);
modelBuilder.Entity().HasRequired(c=>c.MainEntity)。with可选(p=>p.DetailEntity);
}
公共虚拟数据库集MainEntities{get;set;}
公共虚拟DbSet DetailEntities{get;set;}
}
公共类主实体
{
公共int Id{get;set;}
public DetailEntity DetailEntity{get;set;}
}
公共类实体
{
公共int Id{get;set;}
公共maintentity maintentity{get;set;}
}

也许这是一个术语问题。 在Code first EF中,EF不允许您与Principal和Dependent具有1:1的关系,两者都具有外键 或者依赖项有自己的主键,而主键与主体无关。 在您的示例中,似乎需要两个导航属性。 严格地说,这不是1:1。因为同一个表有两个关系。 您有2个类型为1:1的关系。。英孚认为这一数字为1比1

如果您有一个真正的1:1关系,EF将希望依赖项与主键具有相同的主键。
您可以在Principal和dependent上定义多个导航属性,从而生成索引

因此,您可能希望调查多对1配置 如果希望主键具有DB级别的可选外键,则需要稍后在迁移期间或使用脚本添加此FK。 但可以说,这最好被视为业务逻辑/规则检查,而不是主体上的可选FK。 因此,在匹配数据库上可能的内容时存在限制。
但值得怀疑的是,在代码优先的场景中,它实际上是必要的

顺便说一句,这里的巧妙技巧是首先在DB中精确地建模您想要的代码。 这里使用EF Powertool nuget从DB中重新解析工程师代码

例如,mini DB仅具有所需的表关系。 在解决方案中创建一个新项目。安装实体框架Powertools。 然后在新项目中使用右键单击选项“首先从DB反向工程代码”

它展示了如何首先在代码中构建它,如果它可以…:-)

我认为你想要实现的。。。请参阅代码示例(如果我误解了您的观点,请原谅),如果加载了NUGET,则应执行代码

 using System.Data.Entity;
    namespace EF_DEMO
    {
    class FK121
    {
        public static void ENTRYfk121(string[] args)
        {
            var ctx = new Context121();
            ctx.Database.Create();
            System.Console.ReadKey();
        }
    }
    public class Main
    {
         public int MainId { get; set; }
         public string BlaMain { set; get; }
         public int? Sub1Id   { set; get; }    // Must be nullable since we want to use EF foreign key
         public int? Sub2Id { set; get; } // Must be nullable since we want to use EF foreign key
        public virtual Sub Sub1 { get; set; }  // Reverse navigation
        public virtual Sub Sub2 { get; set; }  // Reverse navigation
        //  you may also need
        public virtual ICollection<Sub> Subs { get; set; }
    }
    public class Sub
    {
       public int SubId { get; set; }   // Deliberately DIFFERENT KEY TO MAIN.... not 1:1 so this is possible 
       public string blasub { set; get; }
       public int MainId { set; get; } //set in API   , this the FK  
       public virtual Main Main { get; set; } // van to Principal
    }
    public class Context121 : DbContext
    {
        static Context121()
        {
            Database.SetInitializer(new DropCreateDatabaseIfModelChanges<Context121>());
        }
        public Context121()
            : base("Name=Demo") { } // webconfig required to match 
        public DbSet<Main> Mains { get; set; }
        public DbSet<Sub> Subs { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Main>().HasKey(t => t.MainId)
                        .HasOptional(t => t.Sub1)
                        .WithMany()
                        .HasForeignKey(t=>t.Sub1Id) ; // tell EF the field is in POCO, use this please, otherwise it will create it.

            modelBuilder.Entity<Main>()
                        .HasOptional(t => t.Sub2).WithMany()
                        .HasForeignKey(t=>t.Sub2Id);

            modelBuilder.Entity<Sub>()
                        .HasKey(t => t.SubId)
                        .HasRequired(q => q.Main)
                        .WithMany()
                        .HasForeignKey(t => t.MainId);
        }
    }
}
使用System.Data.Entity;
命名空间EF_演示
{
FK121类
{
公共静态void入口FK121(字符串[]args)
{
var ctx=新上下文121();
ctx.Database.Create();
System.Console.ReadKey();
}
}
公共班机
{
public int MainId{get;set;}
公共字符串{set;get;}
public int?Sub1Id{set;get;}//必须为空,因为我们要使用EF外键
public int?Sub2Id{set;get;}//必须为空,因为我们要使用EF外键
公共虚拟子Sub1{get;set;}//反向导航
公共虚拟子Sub2{get;set;}//反向导航
//您可能还需要
公共虚拟ICollection子{get;set;}
}
公开课小组
{
public int SubId{get;set;}//故意将不同的键设置为MAIN….而不是1:1,所以这是可能的
公共字符串blasub{set;get;}
public int MainId{set;get;}//set在API中,这是FK
公共虚拟主Main{get;set;}//van to Principal
}
公共类Context121:DbContext
{
静态上下文121()
{
SetInitializer(新的DropCreateDatabaseIfModelChanges());
}
公共上下文121()
:base(“Name=Demo”){}//webconfig需要匹配
公共数据库集干线{get;set;}
公共DbSet Subs{get;set;}
保护覆盖
 using System.Data.Entity;
    namespace EF_DEMO
    {
    class FK121
    {
        public static void ENTRYfk121(string[] args)
        {
            var ctx = new Context121();
            ctx.Database.Create();
            System.Console.ReadKey();
        }
    }
    public class Main
    {
         public int MainId { get; set; }
         public string BlaMain { set; get; }
         public int? Sub1Id   { set; get; }    // Must be nullable since we want to use EF foreign key
         public int? Sub2Id { set; get; } // Must be nullable since we want to use EF foreign key
        public virtual Sub Sub1 { get; set; }  // Reverse navigation
        public virtual Sub Sub2 { get; set; }  // Reverse navigation
        //  you may also need
        public virtual ICollection<Sub> Subs { get; set; }
    }
    public class Sub
    {
       public int SubId { get; set; }   // Deliberately DIFFERENT KEY TO MAIN.... not 1:1 so this is possible 
       public string blasub { set; get; }
       public int MainId { set; get; } //set in API   , this the FK  
       public virtual Main Main { get; set; } // van to Principal
    }
    public class Context121 : DbContext
    {
        static Context121()
        {
            Database.SetInitializer(new DropCreateDatabaseIfModelChanges<Context121>());
        }
        public Context121()
            : base("Name=Demo") { } // webconfig required to match 
        public DbSet<Main> Mains { get; set; }
        public DbSet<Sub> Subs { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Main>().HasKey(t => t.MainId)
                        .HasOptional(t => t.Sub1)
                        .WithMany()
                        .HasForeignKey(t=>t.Sub1Id) ; // tell EF the field is in POCO, use this please, otherwise it will create it.

            modelBuilder.Entity<Main>()
                        .HasOptional(t => t.Sub2).WithMany()
                        .HasForeignKey(t=>t.Sub2Id);

            modelBuilder.Entity<Sub>()
                        .HasKey(t => t.SubId)
                        .HasRequired(q => q.Main)
                        .WithMany()
                        .HasForeignKey(t => t.MainId);
        }
    }
}
 <connectionStrings>
   <add name="Demo" connectionString="Data Source=localhost;Initial Catalog=Demo;Integrated Security=True;MultipleActiveResultSets=True;App=EntityFramework"
        providerName="System.Data.SqlClient" />
  </connectionStrings>