将生成的主键作为外键插入来自控制器的不同 table
Insert generated primary key as foreign key in different table from controller
我有多个模型,所有这些模型都在一个视图模型中。我在控制器中的一个动作方法是用来向数据库添加数据。
我正在使用 Entity Framework 代码优先迁移
这些 table 的主键正在使用 Entity Framework ID,因此这些是自动生成的。
所有这些模型都通过外键相互依赖。我正在尝试将数据同时插入这些模型数据库 tables。
如何获取一个 table 的主键并将其作为外键插入不同的 table?
Booking
、Messages
和 Items
是不同的模型 classes
Booking
型号 class
public class Booking
{
[Key]
[Column("lngBookingID")]
public Int32 BookingID { get; set; }
public double BookingCost { get; set; }
}
Messages
型号 class:
public class Messages
{
[Key]
[Column("lngMessageID")]
public Int32 MessageID { get; set; }
public string MessageSubject { get; set; }
[ForeignKey("Booking")]
public Int32 lngBookingID { get; set; }
public Booking Booking { get; set; }
}
动作方法代码。 BookingViewModel bvm
拥有所需的所有数据:
_context.Booking.Add(bvm.Booking);
_context.Messages.Add(bvm.Messages);
_context.PetInformation.Add(bvm.items);
_context.SaveChanges();
当我将其添加到数据库时,我希望生成的预订 ID 成为消息 table 中的外键。
您需要确保消息中的预订参考指向与您要添加的预订相同的实例。 EF 将从那里管理 FK 协会。
例如:
bvm.Messages.Booking = bvm.Booking; // Associate the same reference.
_context.Booking.Add(bvm.Booking);
_context.Messages.Add(bvm.Messages);
_context.SaveChanges();
我会避免在视图模型中传递实体 类 因为这可能会导致各种问题,因为您可能认为您正在传递一个实体,但实际上您只是在传递一个 POCO 数据实例与上下文无关。 EF 会将每个 de-serialized 实例都视为一个新引用,即使它们具有匹配的 ID。您必须将它们与 DbContext 相关联,并更新对可能已经关联的实例的引用。它很丑陋,容易出错,也容易被恶意用户未经授权的数据操作。
例如:假设一个场景需要以下数据:
Booking { Id = 0 }, Message { Id = 0, Booking { Id = 0 }}
因此它接受一个 ID 为 0 的新预订,以及一条引用我们新预订的新消息。
当我们调用 context.Booking.Add(booking)
时,EF 将创建一个带有 auto-generated ID 的新预订。比方说,“15”。当它到达消息时,消息包含一个新的、不同的预订参考,因此 EF 将其插入并获得 ID 16。(即使有关预订的其余数据与传入的第一个数据相同)因为这两个预订参考不指向同一个实例,所以它们也被 EF 视为两个完全独立的实例。通过在我们的方法中将消息的预订参考设置为第一个,当 EF 更新预订时,消息的预订参考将指向第一个的 ID。
为了避免像这样的各种丑陋,我们要避免重复引用。如果我们有一个方法可以插入带有可选消息的新预订,那么与其传递会造成此类问题的实体,不如传递常规 C# 视图模型,然后在服务器上处理实体创建(或加载)。像这样传递到方法中的实体实际上只是 POCO 类,但它们包含的数据比您不应该 "trust" 更新到数据库的数据多得多。通过传递一个单独的视图模型,我们实施了一个更好的实践:
从当前 DBContext 加载现有实体引用,and/or 根据提供的数据创建和关联实体。
因此,创建带有可选消息的新预订的方法可能看起来更像:
public ActionResult AddBooking(BookingViewModel booking, MessageViewModel message)
{
var newBooking = new Booking { BookedDate = booking.BookedDate, /* ... */ };
_context.Bookings.Add(newBooking);
if (message != null)
{
var newMessage = new Message { MessageText = message.Text, Booking = newBooking };
_context.Messages.Add(newMessage);
}
_context.SaveChanges();
}
预订实体拥有一组消息会更好。我怀疑您最初可能尝试过此操作,但 运行 在尝试将预订传递给客户时遇到序列化问题。 (不传递实体的另一个原因)
public ActionResult AddBooking(BookingViewModel booking, MessageViewModel message)
{
var newBooking = new Booking { BookedDate = booking.BookedDate, /* ... */ };
if (message != null)
{
var newMessage = new Message { MessageText = message.Text, Booking = newBooking };
newBooking.Messages.Add(newMessage);
}
_context.Bookings.Add(newBooking);
_context.SaveChanges();
}
这利用了实体之间的关系,因此上下文不必将每个实体都视为顶级实体。保存预订时,它的消息也将被保存,FK 参考将自动填写。
当您进入编辑场景等时,继续传递实体引用将导致更多的重复数据痛苦,以及有关已跟踪具有匹配 ID 的实体的上下文错误。这不值得一团糟。 :)
我有多个模型,所有这些模型都在一个视图模型中。我在控制器中的一个动作方法是用来向数据库添加数据。
我正在使用 Entity Framework 代码优先迁移
这些 table 的主键正在使用 Entity Framework ID,因此这些是自动生成的。
所有这些模型都通过外键相互依赖。我正在尝试将数据同时插入这些模型数据库 tables。
如何获取一个 table 的主键并将其作为外键插入不同的 table?
Booking
、Messages
和 Items
是不同的模型 classes
Booking
型号 class
public class Booking
{
[Key]
[Column("lngBookingID")]
public Int32 BookingID { get; set; }
public double BookingCost { get; set; }
}
Messages
型号 class:
public class Messages
{
[Key]
[Column("lngMessageID")]
public Int32 MessageID { get; set; }
public string MessageSubject { get; set; }
[ForeignKey("Booking")]
public Int32 lngBookingID { get; set; }
public Booking Booking { get; set; }
}
动作方法代码。 BookingViewModel bvm
拥有所需的所有数据:
_context.Booking.Add(bvm.Booking);
_context.Messages.Add(bvm.Messages);
_context.PetInformation.Add(bvm.items);
_context.SaveChanges();
当我将其添加到数据库时,我希望生成的预订 ID 成为消息 table 中的外键。
您需要确保消息中的预订参考指向与您要添加的预订相同的实例。 EF 将从那里管理 FK 协会。
例如:
bvm.Messages.Booking = bvm.Booking; // Associate the same reference.
_context.Booking.Add(bvm.Booking);
_context.Messages.Add(bvm.Messages);
_context.SaveChanges();
我会避免在视图模型中传递实体 类 因为这可能会导致各种问题,因为您可能认为您正在传递一个实体,但实际上您只是在传递一个 POCO 数据实例与上下文无关。 EF 会将每个 de-serialized 实例都视为一个新引用,即使它们具有匹配的 ID。您必须将它们与 DbContext 相关联,并更新对可能已经关联的实例的引用。它很丑陋,容易出错,也容易被恶意用户未经授权的数据操作。
例如:假设一个场景需要以下数据:
Booking { Id = 0 }, Message { Id = 0, Booking { Id = 0 }}
因此它接受一个 ID 为 0 的新预订,以及一条引用我们新预订的新消息。
当我们调用 context.Booking.Add(booking)
时,EF 将创建一个带有 auto-generated ID 的新预订。比方说,“15”。当它到达消息时,消息包含一个新的、不同的预订参考,因此 EF 将其插入并获得 ID 16。(即使有关预订的其余数据与传入的第一个数据相同)因为这两个预订参考不指向同一个实例,所以它们也被 EF 视为两个完全独立的实例。通过在我们的方法中将消息的预订参考设置为第一个,当 EF 更新预订时,消息的预订参考将指向第一个的 ID。
为了避免像这样的各种丑陋,我们要避免重复引用。如果我们有一个方法可以插入带有可选消息的新预订,那么与其传递会造成此类问题的实体,不如传递常规 C# 视图模型,然后在服务器上处理实体创建(或加载)。像这样传递到方法中的实体实际上只是 POCO 类,但它们包含的数据比您不应该 "trust" 更新到数据库的数据多得多。通过传递一个单独的视图模型,我们实施了一个更好的实践: 从当前 DBContext 加载现有实体引用,and/or 根据提供的数据创建和关联实体。
因此,创建带有可选消息的新预订的方法可能看起来更像:
public ActionResult AddBooking(BookingViewModel booking, MessageViewModel message)
{
var newBooking = new Booking { BookedDate = booking.BookedDate, /* ... */ };
_context.Bookings.Add(newBooking);
if (message != null)
{
var newMessage = new Message { MessageText = message.Text, Booking = newBooking };
_context.Messages.Add(newMessage);
}
_context.SaveChanges();
}
预订实体拥有一组消息会更好。我怀疑您最初可能尝试过此操作,但 运行 在尝试将预订传递给客户时遇到序列化问题。 (不传递实体的另一个原因)
public ActionResult AddBooking(BookingViewModel booking, MessageViewModel message)
{
var newBooking = new Booking { BookedDate = booking.BookedDate, /* ... */ };
if (message != null)
{
var newMessage = new Message { MessageText = message.Text, Booking = newBooking };
newBooking.Messages.Add(newMessage);
}
_context.Bookings.Add(newBooking);
_context.SaveChanges();
}
这利用了实体之间的关系,因此上下文不必将每个实体都视为顶级实体。保存预订时,它的消息也将被保存,FK 参考将自动填写。
当您进入编辑场景等时,继续传递实体引用将导致更多的重复数据痛苦,以及有关已跟踪具有匹配 ID 的实体的上下文错误。这不值得一团糟。 :)