整个错误:
外键属性“Appointment.CustomerId1”是在阴影状态下创建的,因为实体类型中存在简单名称为“CustomerId”的冲突属性,但该属性未Map、已用于另一个关系或与关联的主键类型不兼容。
数据表:
Appointment
User
在“预约”表中,我有2个FK:一个指向Customer表(Id列),另一个添加到Employee表(Id列)。请参见BEFORE部分的图片。但现在,因为我将所有用户(customer + employee)在同一个表User中,它必须改变。这意味着在Appointment表中我需要有2个FK,但它们都需要指向同一个表User,和“ID”列。我希望CustomerId和EmployeeId指向来自用户的ID。
它会建立3个额外的数据行:UserId、CustomerId 1和EmployeeId 1--我不需要它们。我只对关系使用了Conventions,没有使用Data Annotations或Fluent API。
有3种情况可能导致错误:
- 1.未Map
- 1.已用于另一关系
- 1.与关联的主键类型不兼容
据我了解 - 1.不是我的情况,因为数据类型是相同的(字符串)。
- 1.不是我的案子,因为我没有其他关系。
- 1.可能有问题,但我不确定。我可能需要为这个Map添加一些Fluent Api。这是我尝试过的,但它不起作用:https://i.stack.imgur.com/UFrC6.png
双向方法:
使用者类别:
public ICollection<Appointment> AppointmentCustomers { get; set; }
public ICollection<Appointment> AppointmentEmployees { get; set; }
预约类别:
public string CustomerId { get; set; }
[ForeignKey("CustomerId")]
public User Customer { get; set; }
public string EmployeeId { get; set; }
[ForeignKey("EmployeeId")]
public User Employee { get; set; }
OnModel创建方法:
builder.Entity<Appointment>()
.HasOne(u => u.Customer)
.WithMany(app => app.AppointmentCustomers)
.HasForeignKey(u => u.CustomerId)
.OnDelete(DeleteBehavior.NoAction);
builder.Entity<Appointment>()
.HasOne(u => u.Employee)
.WithMany(app => app.AppointmentEmployees)
.HasForeignKey(u => u.EmployeeId)
.OnDelete(DeleteBehavior.NoAction);
2条答案
按热度按时间bf1o4zei1#
以前,EF可以通过约定来计算键。约定基于类型名称(Employee vs. Customer)而不是变量名称。如果您将外键命名为EmployeeKey/EmpID和CustomerKey/CustID,您将遇到类似的问题。EF的约定不会将它们作为外键关联,因此它将创建影子属性。
现在您将这两个属性都指向同一个Type(User)EF不能使用约定,所以您必须显式地使用。解决这个问题最简单的方法是使用
[ForeignKey]
属性。这可以放在FK属性上以指向navigation属性,也可以放在navigation属性上以指向FK。即
或
编辑:
您现在得到的错误是因为用户有一个约会集合,但您必须告诉EF此FK链接到哪个集合。这里您有一个约会,它引用了两个用户,一个客户和一个员工。从用户的Angular 来看,有两个不同的关系。“约会-我是客户”和“约会-我是员工”。
如果您只对一种关系感兴趣,则需要配置EF以基于“约会客户”或“员工”关系Map“用户.约会.”如果您对两种关系都感兴趣,则有两个选项.
a)向User添加2个Appointments集合,即AppointmentsAsCustomer和AppointmentsAsEmployee,并在模型构建器或EntityTypeConfiguration中设置Map。b)删除User上的Appointments集合,并使用
.HasOne(x => x.Customer).WithMany()
和.HasOne(x => x.Employee).WithMany()
配置EF,然后当您希望按用户查询约会时,从Appointments执行此操作,而不是期望通过User进行导航:而不是:
用途:
双向引用(其中约会引用用户,而用户引用约会)应仅在绝对需要时而非默认情况下谨慎使用。它们可能导致更新时的怪异行为以及延迟加载的含义,以及像这样的具有模糊关系的“陷阱”。
w9apscun2#
该属性已用于旧的Customer和Employee类中的另一个关系。
(Steve Py's answer在外键配置方面有很大帮助,但从我所读到的内容来看,最好通过Fluent API与Data Annotations进行配置。)