【问题标题】:C# ASP.NET MVC read-only for data field not workingC# ASP.NET MVC 只读数据字段不起作用
【发布时间】:2020-11-19 21:08:06
【问题描述】:

我的编辑表单出现了一些问题,无论我使用什么似乎都无法正常工作。

我试过了

[ReadOnly(true)] and [Editable(false)]

在模型中

@Html.EditorFor(model => model.SellingPrice, new { htmlAttributes = new { @class = "form-control", @readonly = true } })

在视图中..

我已经更改了控制器,但对字段一无所知。

我也试过把模型改成

{ get; private set; }

根据另一个站点上的另一个帖子在模型中使用[ReadOnly(true)] 并且控制器中没有任何东西指向它,它应该出现'null',但它没有。它似乎给出了 0 值或该字段中包含的值。取决于我是否在编辑视图中使用它。

表中的这个字段是SQL端的计算字段。仅用于观看。

以下是控制器 POST - 我尝试过的 2 个版本:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(ProductMaster productMaster)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder();

    try
    {
        if (ModelState.IsValid)
        {
            ProductMaster prodFromDB = db.ProductMaster.Single(x => x.ProductMasterId == productMaster.ProductMasterId);

            prodFromDB.VendorId = productMaster.VendorId;
            prodFromDB.Material = productMaster.Material;
            prodFromDB.VendorRef = productMaster.VendorRef;
            prodFromDB.CreatedDate = productMaster.CreatedDate;
            prodFromDB.CreatedBy = productMaster.CreatedBy;
            prodFromDB.LastUpdated = productMaster.LastUpdated;
            prodFromDB.UpdatedBy = productMaster.UpdatedBy;
            prodFromDB.UnitOfMeasure = productMaster.UnitOfMeasure;
            prodFromDB.StandardCost = productMaster.StandardCost;
            prodFromDB.AverageCost = productMaster.AverageCost;
            prodFromDB.LastCost = productMaster.LastCost;
            prodFromDB.IsPrimary = productMaster.IsPrimary;

            var Manager = ((IObjectContextAdapter)db).ObjectContext.ObjectStateManager;
            Manager.ChangeObjectState(prodFromDB, System.Data.Entity.EntityState.Modified);

            db.SaveChanges();

            sb.Append("Submitted");
            return Content(sb.ToString());
        }
        else
        {
            foreach (var key in this.ViewData.ModelState.Keys)
            {
                foreach (var err in this.ViewData.ModelState[key].Errors)
                {
                    sb.Append(err.ErrorMessage + "<br/>");
                }
            }
        }
    }
    catch (Exception ex)
    {
        sb.Append("Error :" + ex.Message);
    }

    return Content(sb.ToString());
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ProductMasterId,VendorId,Material,VendorRef,CreatedDate,CreatedBy,LastUpdated,UpdatedBy,UnitOfMeasure,StandardCost,AverageCost,LastCost,IsPrimary")] ProductMaster productMaster)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder();

    try
    {
        if (ModelState.IsValid)
        {
            db.Entry(productMaster).State = EntityState.Modified;
            db.SaveChanges();

            sb.Append("Submitted");
            return Content(sb.ToString());
        }
        else
        {
            foreach (var key in this.ViewData.ModelState.Keys)
            {
                foreach (var err in this.ViewData.ModelState[key].Errors)
                {
                    sb.Append(err.ErrorMessage + "<br/>");
                }
            }
        }
    }
    catch (Exception ex)
    {
        sb.Append("Error :" + ex.Message);
    }

    return Content(sb.ToString());
}

我得到的错误是:

无法修改“SellingPrice”列,因为它是计算列或者是 UNION 运算符的结果

【问题讨论】:

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


    【解决方案1】:

    首先要使用 Computed 的 DatabaseGeneratedOption 标记 Entity 属性:

    public class Product
    {
        // ...
        [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
        public decimal SellingPrice { get; internal set; }
    
        // ...
    }
    

    接下来要避免将实体的 EntityState 设置为显式修改的代码。只要 DbContext 正在跟踪实体,这就足够了:

    ProductMaster prodFromDB = db.ProductMaster.Single(x => x.ProductMasterId == productMaster.ProductMasterId);
    
    prodFromDB.VendorId = productMaster.VendorId;
    prodFromDB.Material = productMaster.Material;
    prodFromDB.VendorRef = productMaster.VendorRef;
    prodFromDB.CreatedDate = productMaster.CreatedDate;
    prodFromDB.CreatedBy = productMaster.CreatedBy;
    prodFromDB.LastUpdated = productMaster.LastUpdated;
    prodFromDB.UpdatedBy = productMaster.UpdatedBy;
    podFromDB.UnitOfMeasure = productMaster.UnitOfMeasure;
    prodFromDB.StandardCost = productMaster.StandardCost;
    prodFromDB.AverageCost = productMaster.AverageCost;
    prodFromDB.LastCost = productMaster.LastCost;
    prodFromDB.IsPrimary = productMaster.IsPrimary;
    
    db.SaveChanges();
    

    原因是假设我有一个包含 20 列的实体,我从视图模型更新了其中的 5 个,而这些值中只有 2 个实际上与实体的当前状态不同。如果我让 DbContext 跟踪更改并调用SaveChanges,那么生成的UPDATE SQL 语句将是一个更新,仅指定值实际更改的列。相反,如果我将 EntityState 设置为 Modified,则 UPDATE SQL 语句将包括 all 列,无论我是否设置它们,以及它们是否实际更改.计算列应该被忽略,但为什么要承担更新/覆盖您不打算更改的值的成本/风险?

    【讨论】:

    • 完美,非常感谢,不,我相信最好只更改需要更改或加载的内容。我不知道'EntityState.Modified'做到了。当我只更改了一些东西时,当我看到模型加载中的所有内容时有点困惑。是我自己没有查到的。我认为这意味着它所说的,但在项目级别上。并不是模型状态就是它的意思。然而,这就是实体,不是吗。
    猜你喜欢
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 2016-11-24
    • 2023-03-20
    • 2015-05-06
    • 1970-01-01
    • 2011-01-22
    • 2021-07-29
    相关资源
    最近更新 更多