补充: 想要代码实现的结构为: class A { public int AutoId{get;set;} public string K1{get;set;} public string K2{get;set;} public string K3{get;set;} public string P1{get;set;} public string P2{get;set;} public IList<B> BList{get;set;} }class B { public int AutoId{get;set;} public string K1{get;set;} public string K2{get;set;} public string K3{get;set;} public string P3{get;set;} public string P4{get;set;} public A A{get;set;} }
非常感谢“github_22161131”大神的热心答复! 我觉得你说的很有道理,不过数据库我是动不了的,那么如果我把A-B的关系变为多对多,使用这种关联可以么?(可以使用CodeFirst的方式)即:class A { public int AutoId{get;set;} public string K1{get;set;} public string K2{get;set;} public string K3{get;set;} public string P1{get;set;} public string P2{get;set;} public ICollection<B> BList{get;set;} }class B { public int AutoId{get;set;} public string K1{get;set;} public string K2{get;set;} public string K3{get;set;} public string P3{get;set;} public string P4{get;set;} public ICollection<A> AList{get;set;} }
好的 感谢github_22161131的回答,受益良多,顺便问一句;EF 6的CodeFirst模式支持继承么?即:[NoMapped] public class EntityBase { [Key] public int AutoId{get;set;} public string K1{get;set;} public string K2{get;set;} public string K3{get;set;} } public class A : EntityBase { pubilc string P1{get;set;} pubilc string P2{get;set;} } public class B: EntityBase { pubilc string P3{get;set;} pubilc string P4{get;set;} }要实现类似这样的结构设计 应该如何实现呢?
支持继承,EF的继承关系映射到数据库有三种方式,我简单说 1. Table per Hierarchy (TPH) 就是基类和子类都映射到一张表,通过一个额外的字段区别是那个类。 2. Table per Type (TPT) 就是每个类一张表,子类表和基类表是主键关联1:1的关系。3. Table per Concrete Type (TPC) 就是基类不映射,而是其属性都在子类展开,每个子类一张表。像你给的结构应该是用TPC,和之前一样映射到A,B两张表。这个最简单,写成public abstract class EntityBase { [Key] public int AutoId{get;set;} public string K1{get;set;} public string K2{get;set;} public string K3{get;set;} } public class A : EntityBase { pubilc string P1{get;set;} pubilc string P2{get;set;} } public class B: EntityBase { pubilc string P3{get;set;} pubilc string P4{get;set;} }这样基类是abstract的,EF就自动TPC了。具体的说明我觉得写的比较详细的是http://weblogs.asp.net/manavi/associations-in-ef-4-1-code-first-part-1-introduction-and-basic-concepts
想要代码实现的结构为:
class A
{
public int AutoId{get;set;}
public string K1{get;set;}
public string K2{get;set;}
public string K3{get;set;}
public string P1{get;set;}
public string P2{get;set;}
public IList<B> BList{get;set;}
}class B
{
public int AutoId{get;set;}
public string K1{get;set;}
public string K2{get;set;}
public string K3{get;set;}
public string P3{get;set;}
public string P4{get;set;}
public A A{get;set;}
}
既然表B里的内容和表A的一样,那它就完全没必要出现在表B里
你应该这样设计:
表A
AutoId,K1,K2,K3,P1,P2
表B
AutoId,AID,P3,P4
用AID于表A的AutoId关联就可以了
public class A
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int AutoId { get; set; } [Key, Column(Order = 0)]
public string K1 { get; set; }
[Key, Column(Order = 1)]
public string K2 { get; set; }
[Key, Column(Order = 2)]
public string K3 { get; set; } public string P1 { get; set; }
public string P2 { get; set; } public virtual ICollection<B> BList { get; set; }
}public class B
{
[Key]
public int AutoId { get; set; } [ForeignKey("A"), Column(Order = 0)]
public string K1 { get; set; }
[ForeignKey("A"), Column(Order = 1)]
public string K2 { get; set; }
[ForeignKey("A"), Column(Order = 2)]
public string K3 { get; set; } public string P3 { get; set; }
public string P4 { get; set; } public virtual A A { get; set; }
}
1. 这个Order就是Key的标识么?
2. 这个是CodeFirst的模式吧,如果我使用DBFirst,然后在用.edmx的视图编辑应该如何操作呢?
3. 如果A表中K1,K2,K3不唯一.........这样做会抛错么?
2. 我试验了下,DbFirst的约束更大,要看你数据库的结构了,如果原来A表的主键是AutoId,那DbFirst做不到直接映射,它的关联必须是外键和主键关联的,就没法把B上的(K1,K2,K3)关联到A的(K1,K2,K3)了。如果A上的主键本来就是(K1,K2,K3)那就可以映射。
3. (K1,K2,K3)组合键必须唯一,否则从B关联A就不是一种情况,这样肯定不能直接关联了。我估计你的情况是数据库里面A表主键是AutoId,K1,K2,K3也并没有做唯一键约束,这样是没法在数据库和EF层面关联的。如果要关联就要保证A表的(K1,K2,K3)组合唯一,在数据库A表建立(K1,K2,K3)的唯一键约束,B表就可以建立外键关联了。只有这样EF才能使用这个关联来做entity上的属性关联。如果你的数据库可以做上面说的改动,那DbFirst的方式也不支持这样的关联,需要用CodeFirst的方式来自己建立新的DbContext和实体来做查询。CodeFirst也不是非要从code创建、修改数据库结构,我给的例子其实也是我手动建了数据库,然后再用CodeFirst做的(因为CodeFirst的约束比较弱,能支持不关联主键的外键)。如果不能做上面的改动,那就没办法实现直接关联了。
我觉得你说的很有道理,不过数据库我是动不了的,那么如果我把A-B的关系变为多对多,使用这种关联可以么?(可以使用CodeFirst的方式)即:class A
{
public int AutoId{get;set;}
public string K1{get;set;}
public string K2{get;set;}
public string K3{get;set;}
public string P1{get;set;}
public string P2{get;set;}
public ICollection<B> BList{get;set;}
}class B
{
public int AutoId{get;set;}
public string K1{get;set;}
public string K2{get;set;}
public string K3{get;set;}
public string P3{get;set;}
public string P4{get;set;}
public ICollection<A> AList{get;set;}
}
public class EntityBase
{
[Key]
public int AutoId{get;set;}
public string K1{get;set;}
public string K2{get;set;}
public string K3{get;set;}
}
public class A : EntityBase
{
pubilc string P1{get;set;}
pubilc string P2{get;set;}
}
public class B: EntityBase
{
pubilc string P3{get;set;}
pubilc string P4{get;set;}
}要实现类似这样的结构设计 应该如何实现呢?
1. Table per Hierarchy (TPH)
就是基类和子类都映射到一张表,通过一个额外的字段区别是那个类。 2. Table per Type (TPT)
就是每个类一张表,子类表和基类表是主键关联1:1的关系。3. Table per Concrete Type (TPC)
就是基类不映射,而是其属性都在子类展开,每个子类一张表。像你给的结构应该是用TPC,和之前一样映射到A,B两张表。这个最简单,写成public abstract class EntityBase
{
[Key]
public int AutoId{get;set;}
public string K1{get;set;}
public string K2{get;set;}
public string K3{get;set;}
}
public class A : EntityBase
{
pubilc string P1{get;set;}
pubilc string P2{get;set;}
}
public class B: EntityBase
{
pubilc string P3{get;set;}
pubilc string P4{get;set;}
}这样基类是abstract的,EF就自动TPC了。具体的说明我觉得写的比较详细的是http://weblogs.asp.net/manavi/associations-in-ef-4-1-code-first-part-1-introduction-and-basic-concepts