插入具有外键关系的两个表

时间:2015-06-11 23:06:07

标签: sql-server asp.net-mvc entity-framework sql-server-2008 stored-procedures

在我的MVC应用程序中,我有两个名为TicketAttachment的实体,在插入新的故障单记录时,我还想为附件插入新记录,其中包含先前的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; }
}

3 个答案:

答案 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();
}