C# 实体框架关系
我对实体框架有以下问题:
无法确定导航代表的关系 类型'列表'的“预订。参与者”。要么手动 配置关系,或使用 '[notmapped]'属性或使用'entityTypebuilder.ignore' 'onModelCreating'。
这是我的两个课程:
public class Booking
{
[Key]
public int Id { get; set; }
[Required]
public Event? Event { get; set; }
public Invoice? Invoice { get; set; }
[Required]
public Participant? TravelApplicant { get; set; }
public List<Participant>? Participants { get; set; }
[Required]
public int NumberOfParticipants
{
get
{
if (Participants != null)
{
if (TravelApplicant != null)
{
if (TravelApplicant.IsTravelApplicantParticipant)
return Participants.Count + 1;
else
return Participants.Count;
}
}
return 0;
}
set
{
if (Participants != null)
{
if (TravelApplicant != null)
{
if (TravelApplicant.IsTravelApplicantParticipant)
NumberOfParticipants = Participants.Count + 1;
else
NumberOfParticipants = Participants.Count;
}
}
}
}
[Required]
public bool CoronaEntryCheckBox { get; set; }
[Required]
public bool AgbCheckBox { get; set; }
[Required]
public bool NewsletterCheckBox { get; set; }
}
public class Participant
{
[Key]
public int Id { get; set; }
[Required]
public Accommodation? Accommodation { get; set; }
[Required]
public Booking? Booking { get; set; }
[Required]
public Gender Gender { get; set; }
public string? Title { get; set; }
[Required]
public string? FirstName { get; set; }
[Required]
public string? LastName { get; set; }
[Required]
public DateTime? Birthday { get; set; }
[Required]
public string? Street { get; set; }
[Required]
public string? HouseNumber { get; set; }
public string? AdditionalAddress { get; set; }
[Required]
public string? ZipCode { get; set; }
[Required]
public string? City { get; set; }
[Required]
public string? Country { get; set; }
[Required]
public string? EMail { get; set; }
[Required]
public string? Phone { get; set; }
[Required]
public bool IsTravelApplicant { get; set; }
[Required]
public bool IsTravelApplicantParticipant { get; set; }
[Required]
public bool Vegetarian { get; set; }
public string? Note { get; set; }
}
我希望你们中的一个知道解决方案,谢谢您:)
I have the following problem with Entity Framework:
Unable to determine the relationship represented by navigation
'Booking.Participants' of type 'List'. Either manually
configure the relationship, or ignore this property using the
'[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in
'OnModelCreating'.
Here are my two classes:
public class Booking
{
[Key]
public int Id { get; set; }
[Required]
public Event? Event { get; set; }
public Invoice? Invoice { get; set; }
[Required]
public Participant? TravelApplicant { get; set; }
public List<Participant>? Participants { get; set; }
[Required]
public int NumberOfParticipants
{
get
{
if (Participants != null)
{
if (TravelApplicant != null)
{
if (TravelApplicant.IsTravelApplicantParticipant)
return Participants.Count + 1;
else
return Participants.Count;
}
}
return 0;
}
set
{
if (Participants != null)
{
if (TravelApplicant != null)
{
if (TravelApplicant.IsTravelApplicantParticipant)
NumberOfParticipants = Participants.Count + 1;
else
NumberOfParticipants = Participants.Count;
}
}
}
}
[Required]
public bool CoronaEntryCheckBox { get; set; }
[Required]
public bool AgbCheckBox { get; set; }
[Required]
public bool NewsletterCheckBox { get; set; }
}
public class Participant
{
[Key]
public int Id { get; set; }
[Required]
public Accommodation? Accommodation { get; set; }
[Required]
public Booking? Booking { get; set; }
[Required]
public Gender Gender { get; set; }
public string? Title { get; set; }
[Required]
public string? FirstName { get; set; }
[Required]
public string? LastName { get; set; }
[Required]
public DateTime? Birthday { get; set; }
[Required]
public string? Street { get; set; }
[Required]
public string? HouseNumber { get; set; }
public string? AdditionalAddress { get; set; }
[Required]
public string? ZipCode { get; set; }
[Required]
public string? City { get; set; }
[Required]
public string? Country { get; set; }
[Required]
public string? EMail { get; set; }
[Required]
public string? Phone { get; set; }
[Required]
public bool IsTravelApplicant { get; set; }
[Required]
public bool IsTravelApplicantParticipant { get; set; }
[Required]
public bool Vegetarian { get; set; }
public string? Note { get; set; }
}
I hope one of you knows the solution, thank you in advance :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
配置模型时,您如何定义关系?
从外观上看,您仍然需要让实体框架知道如何链接关系。理想情况下,您将拥有为
参与者
存储的bookingID
,如果将其标记为必需
,则不应无效。我会怀疑您实际上希望在
预订
类中定义它:然后在数据库上下文中,您将在
onModeLcreating
Override中遵循此内容。 :您可以通过 https://learlen.microsoft查看完整文档。 com/en-us/ef/core/modeling/
How have you defined the relationship when configuring the model?
From the looks of it you still need to let Entity Framework know how the relationship is linked. Ideally you would have the
BookingId
stored for aParticipant
, which if you have it marked asRequired
should not be nullable.I would suspect you actually want it to be defined in the
Booking
class like so:Then in your database context, you would have something along the lines of this in your
OnModelCreating
override:You can view the full documentation over at https://learn.microsoft.com/en-us/ef/core/modeling/
EF 自动链接关系不一定能解决关系,尤其是当它们重叠时。您看到的问题很可能是因为 Booking 与 Particiant (booking.TravelApplicant) 之间存在多对一关系,并且存在一对多 (booking.Participants) 关系。
Mike 的回答应该让您排序,告诉 EF 使用 Participant.BookingId 链接回解析 booking.Participants,同时您还应该在 Booking 上配置 TravelApplicantId FK 之类的内容来为 TravelApplicant 提供服务。 EF 基于约定的方法尝试根据导航实体的类型而不是属性的名称来查找/使用 FK。这会导致大多数问题,即在依赖约定时多个引用似乎会失败。
我通常不推荐这样的结构,因为虽然暗示 TravelApplicant 将成为 Participant 集合的一部分,但无法在数据级别强制执行此操作。例如,如果我有 PersonA、PersonB 和 PersonC 的参与者,其中 PersonA 是申请人,则没有什么可以阻止我从参与者中删除 PersonA(将他们保留为申请人)或将申请人更改为从未添加到参与者的 PersonD。您当然可以在应用程序级别验证这一点,但在数据级别没有可用的保护。
或者,您可以将其构造为有一个申请人,并且该集合是其他参与者。这意味着当需要所有人时,您总是将申请人附加到参与者中,并且不会防止申请人被添加到参与者关系中。
相反,我将使用的方法是使用多对多关系表 (BookingParticipants),使用 SortOrder 或 IsApplicant 标志等来识别主申请人。这确保了主申请人始终是关联参与者。
使用主申请人是最低索引的排序顺序,并且排序顺序具有唯一约束,因此这满足在数据库级别保护关系和申请人。该标志更具可读性,但缺乏数据级别的保护能力,因为您可能有多个参与者被标记为申请人,或者没有参与者被标记为申请人。 “申请人”可以由实体公开为未映射的属性,以获取正确的参与者,但我建议在使用未映射的属性时使用命名约定,以便轻松识别它们并确保它们不会最终出现在 EF Linq 中表达式。
EF auto-linking relationships will not necessarily resolve relationships especially when they double-up. The issue you are seeing is likely because Booking has both a many-to-one relationship with Particilant (booking.TravelApplicant) and a one-to-many (booking.Participants).
Mike's answer should get you sorted to tell EF to use Participant.BookingId to link back to resolve booking.Participants, while you should also configure something like a TravelApplicantId FK on Booking to service the TravelApplicant. EF's convention-based approach tries to find/use FKs based on the Type of the navigation entity rather than the Name of the property. This causes the majority of issues where multiple references seem to fail when relying on convention.
I don't generally recommend structures like this because while it is implied that TravelApplicant would be part of the Participants collection, there is no way to enforce this at the data level. For example if I have participants of PersonA, PersonB, and PersonC where PersonA is the Applicant, there is nothing stopping me from either removing PersonA from participants (leaving them as applicant) or changing the applicant to PersonD which was never added to Participants. You can of course validate this at the application level but there is no guard available at the data level.
Alternatively you can structure it as having an Applicant and the collection is additional participants. This would mean you would always be appending the applicant to the participants when needing all people, and doesn't guard against the applicant being added to the participants relationship.
Instead, the approach I would use would be to use a many-to-many relationship table (BookingParticipants) using something like a SortOrder or an IsApplicant flag to identify the main applicant. This ensures that the main applicant is always an associated participant.
Using a sort-order where the main applicant is the lowest index, and the sort order has a unique constraint so this satisfies protecting the relationships and applicant at the DB level. The flag is more read-able, but lacks the ability to guard at a data level as you could have multiple participants flagged as Applicant, or no participant flagged as applicant. The "Applicant" can be exposed by an entity as an unmapped property the fetches the correct Participant, though I recommend using a naming convention when working with unmapped properties to make it easy to recognize them and ensure they don't end up in EF Linq expressions.
尝试在代码优先模式下创建关系。
Follow the tutorial: [Configure one to one - Code First][1]
Try create the relationship in code first mode.
Follow the tutorial: [Configure one to one - Code First][1]