我有联系班级
[Table("Contacts")]
public class Contact
{
public string Id { get; set; }
public string Name { get; set; }
}
我有两个继承自Contact的课程:
[Table("Employees")]
public class Employee : Contact
{
public decimal Salary { get; set; }
}
[Table("Suppliers")]
public class Supplier : Contact
{
public string TIN { get; set; }
}
我使用Entity Framework 6.3作为我的ORM。
我可以建模同一联系人可以是员工和 具有相同唯一ID的供应商。
Employee emp = new Employee();
emp.Id = "C1";
emp.Name = "Employees";
emp.Salary = 10000;
emp.TrackingState = TrackingState.Added;
Supplier sup = new Supplier();
sup.Id = "C1";
sup.Name = "Employees";
sup.TIN = "ABC";
sup.TrackingState = TrackingState.Added;
当我这样做时:
context.Employee.Add(emp);
context.Supplier.Add(sup);
context.Save();
显然,它不允许我添加记录。 我收到一个错误:
"违反PRIMARY KEY约束' PK_dbo.Contacts'。无法在对象' dbo.Contacts'中插入重复的密钥。重复键值为(C1)。\ r \ n语句已终止。"
我是否可以使供应商也与员工共享相同的ID 是否允许插入/更新员工和供应商?
由于
答案 0 :(得分:1)
我假设您没有进行任何特定的继承映射,默认情况下会将其映射为每个层次结构(TPH)继承。使用此映射,您将获得一个Db表,其中包含基本类型中所有字段的聚合以及具有鉴别符字段的相关类型,以了解该行应实现的类型。这允许您在要求输入类型时进行查询。
使用TPH,每行只能是一种类型,因此您不能将同一行作为员工和供应商。
你可以做另一种类型的映射,称为Table Per Type(TPT),它将为每种类型创建一个表,因此在你的情况3中,一个用于共享字段,一个用于每个依赖类型。这应该可以满足您的要求。 (YMMV)
但是,似乎员工和供应商将在不同的域中使用,因此我建议您创建联系人表并将其与您的员工和供应商联系起来。
[Table("Contacts")]
public class Contact
{
public string Id { get; set; }
public string Name { get; set; }
}
[Table("Employees")]
public class Employee
{
public string Id { get; set; }
public string ContactId { get; set; }
public decimal Salary { get; set; }
public Contact Contact { get; set; }
}
[Table("Suppliers")]
public class Supplier
{
public string Id { get; set; }
public string ContactId { get; set; }
public string TIN { get; set; }
public Contact Contact { get; set; }
}
现在您可以查询员工:
db.Employees.Include(e => e.Contact).First();
或供应商:
db.Employees.Include(e => e.Contact).First();
哪个可能比您需要的继承查询更清晰:
db.Contacts.OfType<Employee>().First();
在上面显示的Has A建模和使用TPT的Is A Modeling中,你得到三个表。你只需要在我展示的内容中使用FK而不是使用TPT在3个表中使用相同的ID。
你可以看一下Table Per Class,它类似于TPT但是你没有获得抽象/父类的表,而是你得到每个依赖类型的表,其中包含所有字段。我不认为这是你想要的,因为它会有重复数据,但是,它确实意味着更少的连接。