插入到具有外键关系的两个表中
Insert Into two Tables with Foreign Key relationship
在我的 MVC 应用程序中,我有两个名为 Ticket
和 Attachment
的实体,当插入新的工单记录时,我还想插入新的附件记录 先前插入的票证 ID 的 FK。
我查看了一些示例作为 this 页面,但我需要在一个方法中为多个附件使用一个循环,以便用户在创建新工单时可以附加多个文件。你能给Entity Framework的示例存储过程或示例方法来解决这个问题吗?
这是这两个实体:
门票:
public class Ticket
{
[Key]
public int ID { get; set; }
public string Comment { get; set; }
//Navigation Property
public virtual ICollection<Attachment> Attachments { get; set; }
}
附件:
public class Attachment
{
[Key]
public int ID { get; set; }
//Foreign key for Ticket
public int TicketID { get; set; }
public byte[] FileData { get; set; }
public string FileMimeType { get; set; }
//Navigation Property
public virtual Ticket Ticket { get; set; }
}
看看 Entity Framework 中的 AssociationAttribute。它将允许您将对象设置为 属性 以设置外键。如果您添加如下内容:
public class Attachment {
...
[Association(Name = "ticket", ThisKey = "TicketId", OtherKey = "Id", IsForeignKey = true)]
public Ticket Ticket { get; set;}
[Column(DBType = "INT NOT NULL" ...]
public int TicketId { get; set; }
...
}
到您的 class,那么您应该能够像这样将票证对象分配给附件对象的 "Ticket" 属性:
public UploadTicket(string ticketComment, List<Attachment> attachments) {
(using db = new DataContext()) {
var ticket = new ticket();
ticket.Comment = ticketComment;
db.Tickets.InsertOnSubmit(ticket);
foreach (var att in attachments) {
var attachment = new attachment();
attachment.Ticket = ticket; // <- this will assign the TicketId property automatically upon insert
attachment.FileData = att.FileData;
attachment.FileMimeType = att.FileMimeType;
db.Attachments.InsertOnSubmit(attachment);
}
db.SubmitChanges();
}
}
尝试这样的事情(当然这是简化的 - 但它显示了应该使用的基本机制 - 实例化对象并通过它们的导航属性连接它们,并且只为整个对象图保存一次):
// establish the DbContext
using (TicketModel ctx = new TicketModel())
{
// create a ticket
Ticket t1 = new Ticket
{
Comment = "This is ticket #1"
};
// add two attachments to it
Attachment a1 = new Attachment { FileMimeType = "text/json" };
t1.Attachment.Add(a1);
Attachment a2 = new Attachment { FileMimeType = "application/octet-stream" };
t1.Attachment.Add(a2);
// add the ticket to the context
ctx.Ticket.Add(t1);
// save everything
ctx.SaveChanges();
}
有了这个,您的数据库中应该有一张票,以及两个连接的附件(它们的 TicketID
列设置为票的正确值)
通过改进 marc_s 建议的机制,我解决了问题。对于那些需要这种解决方案的人,我发布了最终代码:
控制器中的方法:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult _Create([Bind(Exclude = null)] IssueViewModel ticketViewModel, IEnumerable<HttpPostedFileBase> files)
{
try
{
if (ModelState.IsValid)
{
ticketViewModel.FileAttachments = new List<FileAttachment>();
foreach (var upload in files)
{
if (upload != null && upload.ContentLength > 0)
{
if (upload.ContentType == "application/pdf"
|| upload.ContentType == "application/vnd.openxmlformats-officedocument.word"
|| upload.ContentType == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
{
FileAttachment fileAttachment = new FileAttachment
{
Created = DateTime.Now,
FileMimeType = upload.ContentType,
FileData = new byte[upload.ContentLength]
};
upload.InputStream.Read(fileAttachment.FileData, 0, upload.ContentLength);
ticketViewModel.FileAttachments.Add(fileAttachment);
}
else
{
return PartialView("_Create");
}
}
}
repository.SaveTicket(ticketViewModel.Issue, ticketViewModel.FileAttachments);
return RedirectToAction("Completed");
}
}
catch (RetryLimitExceededException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.)
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
return View(ticketViewModel);
}
数据层中的方法:
public void SaveTicket(Ticket ticket, IEnumerable<FileAttachment> fileAttachment)
{
context.Tickets.Add(ticket);
foreach (FileAttachment f in fileAttachment)
{
context.FileAttachments.Add(f);
}
context.SaveChanges();
}
在我的 MVC 应用程序中,我有两个名为 Ticket
和 Attachment
的实体,当插入新的工单记录时,我还想插入新的附件记录 先前插入的票证 ID 的 FK。
我查看了一些示例作为 this 页面,但我需要在一个方法中为多个附件使用一个循环,以便用户在创建新工单时可以附加多个文件。你能给Entity Framework的示例存储过程或示例方法来解决这个问题吗?
这是这两个实体:
门票:
public class Ticket
{
[Key]
public int ID { get; set; }
public string Comment { get; set; }
//Navigation Property
public virtual ICollection<Attachment> Attachments { get; set; }
}
附件:
public class Attachment
{
[Key]
public int ID { get; set; }
//Foreign key for Ticket
public int TicketID { get; set; }
public byte[] FileData { get; set; }
public string FileMimeType { get; set; }
//Navigation Property
public virtual Ticket Ticket { get; set; }
}
看看 Entity Framework 中的 AssociationAttribute。它将允许您将对象设置为 属性 以设置外键。如果您添加如下内容:
public class Attachment {
...
[Association(Name = "ticket", ThisKey = "TicketId", OtherKey = "Id", IsForeignKey = true)]
public Ticket Ticket { get; set;}
[Column(DBType = "INT NOT NULL" ...]
public int TicketId { get; set; }
...
}
到您的 class,那么您应该能够像这样将票证对象分配给附件对象的 "Ticket" 属性:
public UploadTicket(string ticketComment, List<Attachment> attachments) {
(using db = new DataContext()) {
var ticket = new ticket();
ticket.Comment = ticketComment;
db.Tickets.InsertOnSubmit(ticket);
foreach (var att in attachments) {
var attachment = new attachment();
attachment.Ticket = ticket; // <- this will assign the TicketId property automatically upon insert
attachment.FileData = att.FileData;
attachment.FileMimeType = att.FileMimeType;
db.Attachments.InsertOnSubmit(attachment);
}
db.SubmitChanges();
}
}
尝试这样的事情(当然这是简化的 - 但它显示了应该使用的基本机制 - 实例化对象并通过它们的导航属性连接它们,并且只为整个对象图保存一次):
// establish the DbContext
using (TicketModel ctx = new TicketModel())
{
// create a ticket
Ticket t1 = new Ticket
{
Comment = "This is ticket #1"
};
// add two attachments to it
Attachment a1 = new Attachment { FileMimeType = "text/json" };
t1.Attachment.Add(a1);
Attachment a2 = new Attachment { FileMimeType = "application/octet-stream" };
t1.Attachment.Add(a2);
// add the ticket to the context
ctx.Ticket.Add(t1);
// save everything
ctx.SaveChanges();
}
有了这个,您的数据库中应该有一张票,以及两个连接的附件(它们的 TicketID
列设置为票的正确值)
通过改进 marc_s 建议的机制,我解决了问题。对于那些需要这种解决方案的人,我发布了最终代码:
控制器中的方法:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult _Create([Bind(Exclude = null)] IssueViewModel ticketViewModel, IEnumerable<HttpPostedFileBase> files)
{
try
{
if (ModelState.IsValid)
{
ticketViewModel.FileAttachments = new List<FileAttachment>();
foreach (var upload in files)
{
if (upload != null && upload.ContentLength > 0)
{
if (upload.ContentType == "application/pdf"
|| upload.ContentType == "application/vnd.openxmlformats-officedocument.word"
|| upload.ContentType == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
{
FileAttachment fileAttachment = new FileAttachment
{
Created = DateTime.Now,
FileMimeType = upload.ContentType,
FileData = new byte[upload.ContentLength]
};
upload.InputStream.Read(fileAttachment.FileData, 0, upload.ContentLength);
ticketViewModel.FileAttachments.Add(fileAttachment);
}
else
{
return PartialView("_Create");
}
}
}
repository.SaveTicket(ticketViewModel.Issue, ticketViewModel.FileAttachments);
return RedirectToAction("Completed");
}
}
catch (RetryLimitExceededException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.)
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
return View(ticketViewModel);
}
数据层中的方法:
public void SaveTicket(Ticket ticket, IEnumerable<FileAttachment> fileAttachment)
{
context.Tickets.Add(ticket);
foreach (FileAttachment f in fileAttachment)
{
context.FileAttachments.Add(f);
}
context.SaveChanges();
}