在我的MVC应用程序中,我有两个名为Ticket
和Attachment
的实体,在插入新的故障单记录时,我还想为附件插入新记录,其中包含先前的FK已插入故障单ID 。
我将一些示例看作this页面,但我需要在单个方法中为多个附件使用循环,以便用户在创建新故障单时可以附加多个文件。您能为实体框架提供示例存储过程或示例方法来解决此问题吗?
以下是这两个实体:
票:
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; }
}
答案 0 :(得分:1)
查看实体框架中的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; }
...
}
到你的班级,然后你应该能够为你的附件对象的“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();
}
}
答案 1 :(得分:1)
尝试这样的事情(当然这是简化的 - 但它显示了应该使用的基本机制 - 实例化对象并通过其导航属性连接它们,并且只为整个对象图保存一次):
// 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
列设置为票证的正确值)
答案 2 :(得分:1)
通过改进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();
}