C# Don';如果图像未重新上载到Asp.net mvc,则无法保存空图像数据

C# Don';如果图像未重新上载到Asp.net mvc,则无法保存空图像数据,c#,asp.net,asp.net-mvc,entity-framework,file-upload,C#,Asp.net,Asp.net Mvc,Entity Framework,File Upload,我一直在遵循Apress Pro ASP.NET MVC 3框架手册中的SportsStore示例项目,并尝试将这些概念应用到我的应用程序中。困扰我的一个方面是,在示例中,我可以将图像添加到产品,并将其保存到数据库中,但如果我编辑任何给定的产品,而不为其上载新图像,则图像数据将被清除。我希望能够编辑一个产品,但是如果从HTTPPOST返回的图像数据为空,那么我希望EntityFramework保留现有的图像数据(和内容类型)。如果未上载新图像,如何命令EF不使用null更新此图像字段 [Http

我一直在遵循Apress Pro ASP.NET MVC 3框架手册中的SportsStore示例项目,并尝试将这些概念应用到我的应用程序中。困扰我的一个方面是,在示例中,我可以将图像添加到产品,并将其保存到数据库中,但如果我编辑任何给定的产品,而不为其上载新图像,则图像数据将被清除。我希望能够编辑一个产品,但是如果从HTTPPOST返回的图像数据为空,那么我希望EntityFramework保留现有的图像数据(和内容类型)。如果未上载新图像,如何命令EF不使用null更新此图像字段

[HttpPost]
    public ActionResult Edit(int id, HttpPostedFileBase image1, FormCollection collection)
    {
        using (ISession session = Database.OpenSession())

        {
            try
            {
                DoctorsModel db = new DoctorsModel();
                db.Id_d = id;
                db.D_city = collection["D_city"].ToString();
                db.D_egn = collection["D_egn"].ToString();
                db.D_email = collection["D_email"].ToString();
                db.D_family_name = collection["D_family_name"].ToString();
                db.D_first_name = collection["D_first_name"].ToString();
                db.D_gender = collection["D_gender"].ToString();
                db.D_mid_name = collection["D_mid_name"].ToString();
                db.D_phone = collection["D_phone"].ToString();
                db.D_specialty = collection["D_specialty"].ToString();
                db.D_room = collection["D_room"].ToString();
                db.D_floor = collection["D_floor"].ToString();

                if (image1 != null)
                {
                    db.D_picture = new byte[image1.ContentLength];
                    image1.InputStream.Read(db.D_picture, 0, image1.ContentLength);

                }

                using (ITransaction transaction = session.BeginTransaction())
                {
                    session.SaveOrUpdate(db);
                    transaction.Commit();
                }

                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }
    }
模型


问题是,如果要解决EF的
AddOrUpdate
(用于迁移和初始数据填充场景)或归结为DbContext.Update(医生),那么您的数据将被#null覆盖,那么将尝试使用类似“SaveOrUpdate”的内容。您给EF一个实体来插入或更新,而不考虑已经存在的数据。EF将只执行一个Exists检查,然后根据提供的实体中填充的所有字段发出INSERT或UPDATE*

严格来说,对于RESTful API,您应该通过分别发出
POST
PUT
来区分“添加”和“更新”。在POST中,您获取数据,创建一个新模型,将其添加到DB上下文中,然后
保存更改
。对于
PUT
,获取当前模型,更新适当的值,然后
SaveChanges
。如果找不到行,
PUT
操作不应插入该行

您的方法似乎只用于更新现有记录:

[HttpPut]
public ActionResult Edit(int id, HttpPostedFileBase image1, FormCollection collection)
{
    using (var context = new AppDbContext())
    {
        try
        {
            var doctor = context.Doctors.Single(x => x.Id == id); // Will throw if Dr not found.
            doctor.D_city = collection["D_city"].ToString();
            doctor.D_egn = collection["D_egn"].ToString();
            doctor.D_email = collection["D_email"].ToString();
            doctor.D_family_name = collection["D_family_name"].ToString();
            doctor.D_first_name = collection["D_first_name"].ToString();
            doctor.D_gender = collection["D_gender"].ToString();
            doctor.D_mid_name = collection["D_mid_name"].ToString();
            doctor.D_phone = collection["D_phone"].ToString();
            doctor.D_specialty = collection["D_specialty"].ToString();
            doctor.D_room = collection["D_room"].ToString();
            doctor.D_floor = collection["D_floor"].ToString();

            if (image1 != null)
            {
                doctor.D_picture = new byte[image1.ContentLength];
                image1.InputStream.Read(doctor.D_picture, 0, image1.ContentLength);
            }

            context.SaveChanges();
            return RedirectToAction("Index");
        }
        catch
        {   // do more than this. :)
            return View();
        }
    }
}
理想情况下,DbContext或UnitOfWork被注入。很难知道会话实现做了什么或与DbContext交互。我通常不建议尝试抽象出EF DbContext,因为它实际上削弱了它提供的高效处理数据实体的能力。对于更新操作,获取现有实体,然后跨多个实体复制值。默认情况下,DbContext使用跟踪的实体,因此当您实际更改值时,这些值将包含在UPDATE语句中。任何未显式更改的内容都将保持原样,不会追加到更新查询中

对于像图像这样不经常使用的潜在大数据,我建议考虑将它们隔离到相关的表/实体。即

public class DoctorImage
{
    [Key]
    public int Id { get; set; } // == Doctor.Id
    public byte[] Image { get; set; }
}

其中,医生与医生图像的关系设置为HasOptional.WithRequired/HasOne.WithOne。好处是在与医生打交道时加载图像完全是可选的。除非您在任何地方都明确使用投影,否则加载现有的医生实体将导致EF在您可能不需要的时候每次都获取图像。通过分离它,您仅在显式地加载了渴望/延迟时才能获取它。例如,列出医生可以很容易地完成,而无需加载他们所有的图像数据。

为您的
if(image1!=null)
语句(当图像为null时)放置一个
else
,然后从数据库表中获取图像并为您设置新模型。当我想要更改某些内容时,例如,姓名和我上传了一张照片,但没有更改,而是从数据库中删除
public class DoctorImage
{
    [Key]
    public int Id { get; set; } // == Doctor.Id
    public byte[] Image { get; set; }
}