2

我有实体 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 中支持的东西,或者,为什么会它是个坏主意?

再次感谢,梅林

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

    public int B1_Id {get; set;}
    public B B1 {get; set;}

    public int B2_Id {get; set;}
    public B B2 {get; set;}
}

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

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

        modelBuilder.Entity<A>().HasRequired(c => c.B1).WihOptional().ForeignKey(x=>x.B1_Id);
        modelBuilder.Entity<A>().HasRequired(c => c.B2).WihOptional().ForeignKey(x=>x.B2_Id);
    }
}
4

3 回答 3

4

如果“v-Next”是实体框架 6,那么不,它显然不支持一对一的外键关联,正如您在为 EF 6 计划的所有功能的路线图上看到的那样。

您还可以看到 Unique Constraint 支持不在路线图上,并且在 UserVoice 上仍标记为“Under Review”

因为一对一的外键关联基本上是一对多的关联,在外键列上有一个唯一约束,我希望在唯一约束支持可用之前不会实现一对一的 FK 关联. 如果您希望这A是您两个关系中的主体,则尤其需要它。目前 EF 不支持主体的键不是主键而是具有唯一约束的某些列的关系。

在这篇博文中,该功能被描述并提到它被“推迟”,所以让我们期待 EF 7。

于 2013-02-11T20:40:50.007 回答
1

也许这是一个术语问题。在 Code first EF 中,EF 不允许您与 Principal 和 Dependent 建立 1:1 的关系,既具有彼此的外键,也不允许具有与 Principal 无关的主键的依赖项。在您的示例中,它看起来像是需要 2 个导航属性的情况。严格来说,这不是 1:1。因为您与同一张表有 2 个关系。您有 2 个 1:1 类型的关系。EF 认为这与 1 一样多。

如果您有真正的 1:1 关系,EF 将希望依赖项具有与主项相同的主键。
您可以在 Principle 和dependent 上定义 Multiple NAVIGATION 属性,从而产生索引。

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

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

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

如果可以的话,它显示了如何首先在代码中构建它.... :-)

我认为您想要实现的目标...请参阅代码示例(如果我误解了您的意思,请见谅)如果加载了 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);
        }
    }
}

网络配置....

 <connectionStrings>
   <add name="Demo" connectionString="Data Source=localhost;Initial Catalog=Demo;Integrated Security=True;MultipleActiveResultSets=True;App=EntityFramework"
        providerName="System.Data.SqlClient" />
  </connectionStrings>
于 2013-02-11T12:29:28.000 回答
0

说明你需要解决什么问题?这是 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; }
}
于 2013-02-11T07:43:54.957 回答