【问题标题】:Getting an InvalidCastException within DbUpdateException when updating SQL Server table更新 SQL Server 表时在 DbUpdateException 中获取 InvalidCastException
【发布时间】:2019-07-01 00:00:32
【问题描述】:

我们有一个数据库管理 Web 应用程序,它可以创建、更新和删除我们的 SQL Server 数据库中的条目。该应用程序使用 ASP.NET MVC 并使用 Entity Framework 2.2 构建,在创建和更新数据库中的几乎所有表时都能成功运行。但是,我在更新特定表时遇到了 Db 更新异常。内部异常是一个

无效的转换异常:“无法将'System.String'类型的对象转换为'System.Int32'类型

此表的模型是使用 EF Core Power Tools 创建的,以包含此表中的所有列。我能够毫无问题地在表中创建新条目,但是当我使用应用程序更新 ANY 值时,我得到了异常。有一个用于创建的视图和一个用于编辑的视图。此问题表大约有 50 列,其中包含 2 列和 1 个不可为空的列的串联主列。所有其他列都允许 NULL。

我可以创建一个没有任何问题的填充很少或所有值的记录。我可以在不进行更改的情况下编辑条目。但是每当我对任何字段进行更改时,都会出现错误。

我曾尝试消除字段以尝试缩小特定字段的范围,但没有结果。我已经三重检查了模型类中属性的数据类型是否与表的数据类型一致。一切都是正确的......此外,如果不是,那么我在创建时会遇到同样的错误。

这是我截断的模型类:

public partial class SC_CUSTOM_STYLE_SPEC
{
    [DataTablesAttributeRowId]
    public string RowId { get { return String.Format("{0}_{1}", SELLING_STYLE_NBR, CUST_REFERENCE_NBR); } }
    [Required]
    [StringLength(5)]
    public string SELLING_STYLE_NBR { get; set; }
    [StringLength(2)]
    public string selling_company { get; set; }
    public string density { get; set; }
    [StringLength(100)]
    public string construction_type { get; set; }
    [StringLength(50)]
    public string electrstatic_propensity { get; set; }
    [StringLength(100)]
    public string protective_treatments { get; set; }
    [StringLength(50)]
    public string smoke_density { get; set; }
    [StringLength(50)]
    public string long_name { get; set; }
    public int? introduction_date { get; set; }
    public string stitches_per_inch { get; set; }
    [Required]
    [StringLength(3)]
    public string CUST_REFERENCE_NBR { get; set; }
    [StringLength(50)]
    public string greige_good_nbr { get; set; }
    [StringLength(50)]
    public string inventory_style_nbr { get; set; }
    public bool? is18x36 { get; set; }
    public bool? isHex { get; set; }
    public bool? enableViz { get; set; }
    public bool? enableCustomViz { get; set; }
    public bool? enableGenericViz { get; set; }
    public bool? is9x36Tile { get; set; }
    public bool? isFacetTile { get; set; }
    public int? product_subtype_id { get; set; }
    ...

这是我的控制器中的Create 方法:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("SELLING_STYLE_NBR,selling_company,...")] SC_CUSTOM_STYLE_SPEC sC_CUSTOM_STYLE_SPEC)
{
   if (ModelState.IsValid)
   {
        _context.Add(sC_CUSTOM_STYLE_SPEC);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View(sC_CUSTOM_STYLE_SPEC);
}

这是我的Edit 方法:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(string id, [Bind("SELLING_STYLE_NBR,selling_company,...")] SC_CUSTOM_STYLE_SPEC sC_CUSTOM_STYLE_SPEC)
{
    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(sC_CUSTOM_STYLE_SPEC);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException ex)
        {
            if (!SC_CUSTOM_STYLE_SPECExists(sC_CUSTOM_STYLE_SPEC.SELLING_STYLE_NBR))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        catch (DbUpdateException ex)
        {
            var exception = HandleDbException(ex);
            return View("Error", new System.Web.Mvc.HandleErrorInfo(exception,"SC_CUSTOM_STYLE_SPEC","Edit"));
        }

        // redirect back to List page if referrer is available (only for models with FK)
        var referrer = Request.Form["Referrer"];

        if (String.IsNullOrEmpty(referrer))
            return RedirectToAction(nameof(Index));
        else
            return Redirect(referrer);
    }

    return View(sC_CUSTOM_STYLE_SPEC);
}

这是堆栈:

Microsoft.EntityFrameworkCore.DbUpdateException:发生错误 在更新条目时。有关详细信息,请参阅内部异常。 ---> System.InvalidCastException:无法转换类型的对象 'System.String' 输入 'System.Int32'。

在 System.Data.SqlClient.SqlBuffer.get_Int32()

在 System.Data.SqlClient.SqlDataReader.GetInt32(Int32 i)

在 Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeResultSetWithoutPropagationAsync(Int32 commandIndex、RelationalDataReader 阅读器、CancellationToken 取消令牌)

在 Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeAsync(RelationalDataReader 阅读器,CancellationToken cancelToken)

---内部异常堆栈跟踪结束---

在 CPSDataAdmin.Controllers.SC_CUSTOM_STYLE_SPECController.Edit(字符串 id, SC_CUSTOM_STYLE_SPEC sC_CUSTOM_STYLE_SPEC) 在 C:\Projects\cps-data-admin\CPSDataAdmin\Controllers\SC_CUSTOM_STYLE_SPECController.cs:379 行

在 Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper 映射器,ObjectMethodExecutor 执行器,对象控制器,Object[] 论据)

在 System.Threading.Tasks.ValueTask`1.get_Result()

在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()

在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()

在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext 上下文)

在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(状态& next, Scope& scope, Object& state, Boolean& isCompleted)

在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()

在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()

在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext 上下文)

在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)

在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()

在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()

在 Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)

在 Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext 上下文)

在 Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext 上下文)

在 Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext 上下文)

在 Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)

在 Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)

在 Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext 上下文)

【问题讨论】:

  • 异常在哪一行抛出?如果您可以提供堆栈跟踪,它可能会解释执行SaveChangesAsync() 时出了什么问题。
  • @TetsuyaYamamoto 它在Update 方法中的Update 命令之后在await _context.SaveChangesAsync(); 处中断。我已经在上面添加了堆栈跟踪。

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


【解决方案1】:

检查桌子上的触发器!我在面临同样的问题时发现了这个问题,结果我的问题是执行选择的触发器。

EF 正在运行一个语句

SET NOCOUNT ON;
UPDATE [ProblemTable] SET [IrrelevantColumn] = @p0
WHERE [id] = @p1;
SELECT @@ROWCOUNT;

并且只期望@@rowcount 结果集回来。触发器正在从受影响的行中选择一个 varchar 列,这使得 EF 试图解析来自“ABC1234DEF”的行数。我不知道触发器为什么会执行该选择,但我认为这归结为我的一位前辈在 prod 中调试。

【讨论】:

    【解决方案2】:

    [DataTablesAttributeRowId] 属性是什么?您的表是否有一个名为“RowId”的列?您提到了一个连接的(复合?)键。通常,如果这是由 2x 列组成的 PK,您将声明一个键映射:

    [Key, Column(Order = 0)]
    [Required] 
    [StringLength(5)]
    public string SELLING_STYLE_NBR { get; set; }
    // ...
    [Key, Column(Order = 1)]
    [Required]
    [StringLength(3)]
    public string CUST_REFERENCE_NBR { get; set; }
    

    在数据库中这两个 Varchar/NVarchar 列?在命名暗示它们是数字的系统中使用文本 PK/FK 似乎不寻常。

    实体声明应反映表架构和表之间的关系。为了帮助评估映射问题,请包括相关的表格结构。您的代码示例有一些味道,包括该属性和不同的命名约定。

    【讨论】:

    • 这个应用程序最初不是由我的团队构建的,所以他们添加RowId 的方式有点神秘,但它似乎适用于具有该格式的其他表。正如我上面提到的,它在创建时也没有问题。那么为什么在更新这个表时它会出现问题,而另一个具有相同的表却没有呢?例如,我们有一个颜色规格表,其中有一个由 3 列组成的 RowId,我使用此应用程序更新该表中的条目没有问题。
    猜你喜欢
    • 2016-11-13
    • 2021-04-02
    • 1970-01-01
    • 2012-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多