gpt4 book ai didi

c# - Entity Framework 数据库表关联

转载 作者:行者123 更新时间:2023-12-04 08:41:16 26 4
gpt4 key购买 nike

我有一个这样的域模型:

public class Rental
{
public int Id { get; set; }

public DateTime DateRented { get; set; }
public DateTime? DateReturned { get; set; }

[Required]
public Customer Customer { get; set; }

[Required]
public Movie Movie { get; set; }
}
Entity Framework 将其与其他两个表( CustomersMovies )相关联,并在 Rentals 中自动创建外键列 table 。在我的 .NET 类(class)中,我被教导通过添加 Id 与其他表建立关联。属性,例如 Rental域模型将包含以下属性:
public int MovieId { get; set; }
public int CustomerId { get; set; }
但是代码在没有这些代码行的情况下运行良好。你能向我解释一下哪种方法更好吗?或者其中之一提供了更大的灵活性?我是 .NET 的新手,所以每一个解释都会受到欢迎。

最佳答案

在 EF 定义架构的情况下使用 Code-First 时,EF 将使用约定在表中创建合适的 FK 列并在幕后使用这些列。您可以使用任何您想要的命名约定来定义您自己的 FK,但是您需要告诉 EF 使用哪个列作为哪个表的 FK 关系。这是通过使用 [ForeignKey] 来完成的。属性或使用外键配置关系(modelBuilder 或 EntityTypeConfiguration)。
按照惯例,EF 将通过 定义 FK 列名称。类型 的相关对象,这可能不是您想要的架构。例如,如果您有一个 Order 实体,您希望引用 CreatedBy 和 LastModifiedBy 的 User 实体,您可能希望有类似的东西

public class Order
{
// ...
public virtual User CreatedBy { get; set; }
public virtual User LastModifiedBy { get; set; }
}
EF 会像这样创建 FK:User_Id 和 User_Id2
这可能会绊倒想要在实体中包含 FK 的人:
public class Order
{
// ...
public int CreatedByUserId { get; set; }
public virtual User CreatedBy { get; set; }
public int LastModifiedByUserId { get; set; }
public virtual User LastModifiedBy { get; set; }
}
... 期待它的工作然后想知道为什么表中的 ID 没有被填充。
要使用更有意义的 FK,您需要配置它们:
public class Order
{
// ...
[ForeignKey("CreatedBy")]
public int CreatedByUserId { get; set; }
public virtual User CreatedBy { get; set; }
[ForeignKey("LastModifiedBy")]
public int LastModifiedByUserId { get; set; }
public virtual User LastModifiedBy { get; set; }
}
ForeignKey属性可以放在指向导航属性的 FK 上,也可以放在指向 FK 的导航属性上。
但是,我通常建议不要在实体中定义 FK,因为这可能会在更新引用时导致潜在问题,因为关系有 2 个真实来源。
我是否使用 order.LastModifiedByUserIdorder.LastModifiedBy.UserId ?如果我想更新用户并且某些代码引用了其中的一个怎么办?如果我更改用户导航属性,订单上的 FK 何时更新?如果我设置 FK 而不是导航属性怎么办?
如果我想更新 LastModifiedBy对于订单:
我可能会想这样做:
var order = context.Orders.Single(x => x.OrderId == orderId);
order.LastModifiedByUserId = currentUserId;
但是,我应该这样做:
var currentUser = context.Users.Single(x => x.UserId == currentUserId);
var order = context.Orders.Single(x => x.OrderId == orderId);
order.LastModifiedBy = currentUser;
根据 LastModifiedBy 导航属性是预先加载还是 DBContext 可以填充它(因为它已经加载并且可以在使订单实体饱和时填充)将决定尝试更新 FK 的行为。第二个选项是一致的,但是请注意,即使在那里,订单上的任何 FK 也不会自动更新,直到 SaveChanges叫做。
一般来说,完全避免在实体中暴露 FK 是一个更好的主意。对于 EF6,这可以通过使用 Map.MapKey 来完成。 ,其中 EF Core 支持阴影属性。例如,配置以下实体以定义要使用的 FK 列名称,但避免暴露 FK 属性:
public class Order
{
// ...
public virtual User CreatedBy { get; set; }
public virtual User LastModifiedBy { get; set; }
}
使用模型构建器或 EntityTypeConfigurationEF6
.HasRequired(x => x.CreatedBy)
.WithMany()
.Map(x => x.MapKey("CreatedByUserId"));
.HasRequired(x => x.LastModifiedBy)
.WithMany()
.Map(x => x.MapKey("LastModifiedByUserId"));
英孚核心
.HasOne(x => x.CreatedBy)
.WithMany()
.HasForeignKey("CreatedByUserId");
.HasOne(x => x.LastModifiedBy)
.WithMany()
.HasForeignKey("LastModifiedByUserId");
/w EF 核心 HasForeignKey可用于为 FK 列定义阴影属性,而不是指向实体中的公开属性。这里的优点是相关实体的 key 不再有两个真实来源。

关于c# - Entity Framework 数据库表关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64560569/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com