Entity framework EF代码首先从数据库0..1到多个关系
我试图从现有数据库生成实体框架代码优先模型(不更改数据库模式)。该数据库过去曾用于生成edmx模型,我正在尝试使用Fluent Api或数据注释实现等效模型 我无法使用联接表(不是可为空的外键)重现的关系是0..1对多 所以它看起来像这样:Entity framework EF代码首先从数据库0..1到多个关系,entity-framework,code-first,Entity Framework,Code First,我试图从现有数据库生成实体框架代码优先模型(不更改数据库模式)。该数据库过去曾用于生成edmx模型,我正在尝试使用Fluent Api或数据注释实现等效模型 我无法使用联接表(不是可为空的外键)重现的关系是0..1对多 所以它看起来像这样: TableA { ID (PrimaryKey) TableB (0 or 1) } JoinTable { TableA_FK (PrimaryKey, ForeignKey), TableB_FK (ForeignKey) }
TableA
{
ID (PrimaryKey)
TableB (0 or 1)
}
JoinTable
{
TableA_FK (PrimaryKey, ForeignKey),
TableB_FK (ForeignKey)
}
TableB
{
ID (PrimaryKey)
TableAs (Many)
}
public class JoinTable
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int TableA_FK { get; set; }
public int TableB_FK { get; set; }
//a future property here
public virtual TableA TableA { get; set; }
public virtual TableB TableB { get; set; }
}
public partial class TableA
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TableAId { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
public virtual JoinTable JoinTable { get; set; }
}
public partial class TableB
{
public TableB()
{
JoinTable = new HashSet<JoinTable>();
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TableBId { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
public virtual ICollection<JoinTable> JoinTable { get; set; }
}
}
public partial class Model1 : DbContext
{
public Model1()
: base("name=Model1")
{
}
public virtual DbSet<JoinTable> JoinTable { get; set; }
public virtual DbSet<TableA> TableA { get; set; }
public virtual DbSet<TableB> TableB { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<TableA>()
.HasOptional(e => e.JoinTable)
.WithRequired(e => e.TableA);
modelBuilder.Entity<TableB>()
.HasMany(e => e.JoinTable)
.WithRequired(e => e.TableB)
.HasForeignKey(e => e.TableB_FK)
.WillCascadeOnDelete(false);
}
}
这在代码优先的样式中是可以实现的,还是我必须生成一个edmx模型才能在EF中使用该数据库而不更改其模式
非常感谢,,
Phil如果我理解正确,下面只使用数据注释的代码应该可以创建您的模型
public class TableA
{
public int ID { get; set; }
public JoinTable JoinTable { get; set; }
}
public class TableB
{
public int ID { get; set; }
public List<JoinTable> JoinTables{ get; set; }
}
public class JoinTable
{
[Key, ForeignKey("TableA")]
public int TableA_FK { get; set; }
[ForeignKey("TableB")]
public int TableB_FK { get; set; }
public TableA TableA { get; set; }
public TableB TableB { get; set; }
}
公共类表a
{
公共int ID{get;set;}
公共连接表连接表{get;set;}
}
公共类表格B
{
公共int ID{get;set;}
公共列表连接表{get;set;}
}
公共类可联接
{
[键,外键(“表A”)]
公共int表a_FK{get;set;}
[外键(“表B”)]
公共int TableB_FK{get;set;}
公共表格表格{get;set;}
公共TableB TableB{get;set;}
}
有趣的是,如果您从代码创建的数据库模型生成代码优先的模型,那么EF不会执行返回原始模型的往返过程,EF会简化模型并删除联接表并创建一个可为空的外键
让我知道这是否有效。下面是一个不使用JoinTable类的示例。联接表是通过fluent api配置的
class DataContext : DbContext
{
public DataContext(string connectionString)
: base(connectionString)
{ }
public DbSet<TableA> TableA { get; set; }
public DbSet<TableB> TableB { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<TableA>().ToTable("TableA");
modelBuilder.Entity<TableB>().ToTable("TableB");
modelBuilder.Entity<TableB>()
.HasMany(x => x.TableAs)
.WithMany()
.Map(m =>
{
m.ToTable("JoinTable");
m.MapLeftKey("TableA_FK");
m.MapRightKey("TableB_FK");
});
}
}
class TableA
{
public int ID { get; set; }
public TableB TableB { get; set; }
}
class TableB
{
public int ID { get; set; }
public ICollection<TableA> TableAs { get; set; }
}
我可能错了,但我相信你在这里遗漏了一些概念 如果JoinTable除了外键之外没有任何列,为什么还要有它呢?这没有道理。。。IHMO表a中的可空外键是正确的方法 当您首先使用代码时,这意味着数据库中的所有内容都将由代码表示。没有理由在数据库中有一个表,但在代码中没有 EDMX处理该关系,因为它使用“关联” …首先回到代码,您可以这样表示您的数据库:
TableA
{
ID (PrimaryKey)
TableB (0 or 1)
}
JoinTable
{
TableA_FK (PrimaryKey, ForeignKey),
TableB_FK (ForeignKey)
}
TableB
{
ID (PrimaryKey)
TableAs (Many)
}
public class JoinTable
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int TableA_FK { get; set; }
public int TableB_FK { get; set; }
//a future property here
public virtual TableA TableA { get; set; }
public virtual TableB TableB { get; set; }
}
public partial class TableA
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TableAId { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
public virtual JoinTable JoinTable { get; set; }
}
public partial class TableB
{
public TableB()
{
JoinTable = new HashSet<JoinTable>();
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TableBId { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
public virtual ICollection<JoinTable> JoinTable { get; set; }
}
}
public partial class Model1 : DbContext
{
public Model1()
: base("name=Model1")
{
}
public virtual DbSet<JoinTable> JoinTable { get; set; }
public virtual DbSet<TableA> TableA { get; set; }
public virtual DbSet<TableB> TableB { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<TableA>()
.HasOptional(e => e.JoinTable)
.WithRequired(e => e.TableA);
modelBuilder.Entity<TableB>()
.HasMany(e => e.JoinTable)
.WithRequired(e => e.TableB)
.HasForeignKey(e => e.TableB_FK)
.WillCascadeOnDelete(false);
}
}
公共类JoinTable
{
[关键]
[数据库生成(DatabaseGeneratedOption.None)]
公共int表a_FK{get;set;}
公共int TableB_FK{get;set;}
//这里的未来财产
公共虚拟表格表格{get;set;}
公共虚拟表b TableB{get;set;}
}
公共部分类表a
{
[关键]
[数据库生成(DatabaseGeneratedOption.Identity)]
public int TableAId{get;set;}
[必需]
[长度(50)]
公共字符串名称{get;set;}
公共虚拟连接表连接表{get;set;}
}
公共部分类表B
{
公开表格b(
{
JoinTable=newhashset();
}
[关键]
[数据库生成(DatabaseGeneratedOption.Identity)]
公共int TableBId{get;set;}
[必需]
[长度(50)]
公共字符串名称{get;set;}
公共虚拟ICollection连接表{get;set;}
}
}
公共部分类Model1:DbContext
{
公共模型1()
:base(“name=Model1”)
{
}
公共虚拟数据库集连接表{get;set;}
公共虚拟数据库集表a{get;set;}
公共虚拟数据库集TableB{get;set;}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.has可选(e=>e.JoinTable)
.需要(e=>e.TableA);
modelBuilder.Entity()
.HasMany(e=>e.JoinTable)
.WithRequired(e=>e.TableB)
.HasForeignKey(e=>e.TableB_FK)
.WillCascadeOnDelete(假);
}
}
这似乎接近我想要的。如果TableA可以直接引用它的TableB而不必通过联接表,那么这将是一个完整的答案。这发生在数据库第一个edmx模型方法中-连接表隐藏在模型中。@PhilWithington是的,我知道你的意思。我不知道如何才能做到这一点。您可能有另一个NotMapped
属性取消引用JoinTable
属性。建议不错。不过,缺乏往返可能会在未来产生问题。谢谢你的想法。你几乎都可以用它来做,但我认为这需要在联接表中为表中的每一行指定一行。数据库模型是什么样子的?如果JoinTable
有一个PK/FK引用表a,那么关联只能是*(a)到0..1(B)。我把它弄混了吗?基本上,A可能有一个B(尽管许多人没有),B可能有许多A,尽管大多数人没有。您将得到两个独立的关系:TableA和TableB之间的1:1关系,以及使用联接表的同一个表之间的多:多关系是的,但是如果需要匹配模式,可以避免吗?据我所知,这与问题中描述的模式相匹配。这是我见过的最接近我想要实现的答案。查看代码时让我感到震惊的一个问题是,在迁移过程中,主键在联接表上的位置不太正确,但这可能不是问题,因为数据库已经存在。使用这种方法加载数据时也有问题。我可能在设置中出错,但在模型中找不到指定的表“[JoinTable]”。确保已正确指定表名。我同意可为空的外键更实用,尤其是在首先使用EF代码时。然而,从关系数据库的角度来说,这两种观点都有争议,例如。但在我的例子中,我需要首先从现有数据库中对代码进行反向工程。您的解决方案不像edmx方法那样表示模型。我从来没有说过我的解决方案像edmx那样表示模型。我说的是,在我的心里