无法使用外键将多个文件保存到数据库

Cannot save multiple files to database with Foreign Key

在我的 MVC 应用程序中,我有两个 table,分别称为 TicketAttachment,我想为每个文件保存附件票。问题是:创建新工单 时,我需要使用 TicketID 保存多个附件。所以,我想我应该在 Ticket table 中创建一个新的 ticket,然后获取它的 ID 并将所有具有此 TicketID 的附件循环保存到 Attachment table 中。我看过很多网站和 Whosebug,但在那些页面上没有这样的问题或解决方案。任何的想法?

注意:我使用Entity Framework代码优先,但我也可以使用存储过程或SQL命令进行此操作。

以下是这两个模型:

public class Ticket
{
    [Key] 
    public int ID { get; set; }

    public string Description { get; set; }

    //... removed for clarifty
}


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; }    
}


和控制器方法:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Exclude = null)] TicketViewModel viewModel 
/* contains both model: Ticket and Attachment */, IEnumerable<HttpPostedFileBase> files)
{
    if (ModelState.IsValid)
    {
        //??? First I need to save Ticket
        repository.SaveTicket(viewModel.Ticket);  

        foreach(var f in files)
        {
            viewModel.Attachment.FileMimeType = f.ContentType;
            viewModel.Attachment.FileData = new byte[f.ContentLength];
            f.InputStream.Read(viewModel.Attachment.FileData , 0, f.ContentLength);

            //??? Then save all attachment. But no idea how to get TicketID      
            repository.SaveAttachment(viewModel.Attachment); 
        }
    }   
    return View();
}

ID 属性 将在 SaveChanges 后由 EF 自动填充。然后您的代码就可以使用它。我假设 viewModel.Ticket object 是保存到数据库中的实际 object。如果不行,还请postSaveTicket方法。

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Exclude = null)] TicketViewModel viewModel 
/* contains both model: Ticket and Attachment */, IEnumerable<HttpPostedFileBase> files)
{
    if (ModelState.IsValid)
    {
        // assumes viewModel.Ticket is the actual entity saved, and SaveChanges is called.  
        repository.SaveTicket(viewModel.Ticket);  

        foreach(var f in files)
        {
            viewModel.Attachment.FileMimeType = f.ContentType;
            viewModel.Attachment.FileData = new byte[f.ContentLength];
            f.InputStream.Read(viewModel.Attachment.FileData , 0, f.ContentLength);

            // fill ticket id
            viewModel.Attachment.TicketID = viewModel.Ticket.ID;
            repository.SaveAttachment(viewModel.Attachment); 
        }
    }   
    return View();
}

如果您想在一次交易中完成所有事情,您可以立即添加孩子,SaveChanges 将保存所有 objects:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Exclude = null)] TicketViewModel viewModel 
/* contains both model: Ticket and Attachment */, IEnumerable<HttpPostedFileBase> files)
{
    if (ModelState.IsValid)
    {
        var ticket = viewModel.Ticket;

        foreach(var f in files)
        {
            var attachment = new Attachment();
            attachment.FileMimeType = f.ContentType;
            attachment.FileData = new byte[f.ContentLength];
            f.InputStream.Read(attachment.FileData , 0, f.ContentLength);

            ticket.Attachments.Add(attachment);
        }

        // this will save the ticket and attachments
        repository.SaveTicket(ticket);
    }   
    return View();
}

您的票 class 必须如下所示:

public class Ticket
{
    [Key] 
    public int ID { get; set; }

    public string Description { get; set; }

    // EF will now to use the foreign key to the attachment table
    public virtual ICollection<Attachment> Attachments { get; set; }
}