【问题标题】:Don't save null image data if image was not re-uploaded Asp.net mvc如果图像未重新上传 Asp.net mvc,则不保存空图像数据
【发布时间】:2023-04-02 09:01:01
【问题描述】:

我一直在关注 Apress Pro ASP.NET MVC 3 Framework 书中的 SportsStore 示例项目,并尝试将这些概念应用到我的应用程序中。困扰我的一个方面是,在示例中,我可以将图像添加到产品中并将其保存到数据库中,但是如果我编辑任何给定的产品,而不为它上传新图像,图像数据将被清除.我希望能够编辑产品,但如果从 HTTP 帖子返回的图像数据为空,我希望 Entity Framework 保留现有的图像数据(和内容类型)。如果未上传新图像,如何命令 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();
            }
        }
    }

型号

 public class DoctorsModel
{
    public virtual int Id_d { get; set; }
    [Display (Name ="Име: ")]
    public virtual string D_first_name { get; set; }
    [Display(Name = "Презиме: ")]
    public virtual string D_mid_name { get; set; }
    [Display(Name = "Фамилия: ")]
    public virtual string D_family_name { get; set; }
    [Display(Name = "Специалност: ")]
    public virtual string D_specialty { get; set; }
    [Display(Name = "Пол: ")]
    public virtual string D_gender { get; set; }
    [Display(Name = "Тел.номер: ")]
    public virtual string D_phone { get; set; }
    [Display(Name = "Email: ")]
    public virtual string D_email { get; set; }
    [Display(Name = "ЕГН: ")]
    public virtual string D_egn { get; set; }
    [Display(Name = "Град: ")]
    public virtual string D_city { get; set; }
    [Display(Name = "Снимка: ")]
    public virtual byte[] D_picture { get; set; }
    [StringLength(5)]
    public virtual string D_rating { get; set; }
    public virtual string D_content { get; set; }
    [Display(Name = "Стая:" )]
    public virtual string D_room { get; set; }
    [Display(Name = "Етаж: ")]
    public virtual string D_floor { get; set; }
    
    
}

【问题讨论】:

  • 为您的if (image1 != null) 语句添加一个else(当图像为空时),并从数据库表中获取图像并为您设置新模型。
  • 当我想改变一些东西,例如名字,我上传了一张照片,但它没有改变,它从数据库中删除

标签: c# asp.net asp.net-mvc entity-framework file-upload


【解决方案1】:

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

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

您的方法看起来只是为了更新现有记录:

[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。很难知道您的 Session 实现做什么或与 DbContext 交互。我通常不建议尝试抽象出 EF DbContext,因为它确实削弱了它提供的有效处理数据实体的能力。对于更新操作,获取现有实体,然后复制值。默认情况下,DbContext 使用跟踪的实体,因此当您实际更改值时,这些值将包含在 UPDATE 语句中。任何未明确更改的内容都将保持原样,并且不会附加到 UPDATE 查询中。

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-26
    • 2018-09-05
    • 2017-01-04
    • 1970-01-01
    • 2019-07-17
    • 2019-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多