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

时间:2015-06-11 22:33:08

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

在我的MVC应用程序中,我有两个名为 Ticket 附件的表格,我想保存每张票证的附件。问题是:我需要在创建新故障单时使用 TicketID 保存多个附件。因此,我认为我应该在Ticket表中创建一个新票证然后获取其ID,并将具有此TicketID的所有附件保存到循环中的Attachment表中。我看过很多网站和stackoverflow,但在这些页面上没有这样的问题或解决方案。任何的想法?

注意:我使用Entity Framework Code First,但我也可以使用存储过程或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();
}

1 个答案:

答案 0 :(得分:1)

在SaveChanges之后,ID属性将由EF自动填充。然后您的代码可以使用它。我假设viewModel.Ticket对象是保存到数据库的实际对象。如果没有,请同时发布SaveTicket方法。

[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将保存所有对象:

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

您的Ticket类必须如下所示:

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