【问题标题】:HierarchyID with .NET 5 and EF Core throws cast error使用 .NET 5 和 EF Core 的 HierarchyID 引发转换错误
【发布时间】:2021-11-09 02:45:41
【问题描述】:

我会在一开始就直截了当地说,我不是“真正的”开发人员。我目前正在使用一个宠物项目自学 C#,我遇到了一个绊脚石,到目前为止,谷歌搜索或书评都没有帮助。我认识的少数具有开发背景的人几乎耸了耸肩,就像大多数 Java 之类的人一样,而不是 C#,而使用 C# 的人仍在使用 .NET Core 的先前版本,并且从未在 Entity 中做过任何事情框架。

对于我的项目,我使用的是 .NET Framework 5、EF Core 5.0.9 和最新版本的 SQL Server,并且我正在构建一个 C# Web API。我确实加载了EntityFrameworkCore.SqlServer.HierarchyId 库。 Visual Studio 可以毫无问题地识别 HierarchyId 数据类型,并且数据库和所有表都是通过迁移创建的,所有表在另一侧都具有正确的列数据类型,所以我相当确定我至少有大部分我需要什么。

在 SQL Server 方面,我已经验证我可以在指定的表中手动创建一个项目,并且 HierarchyId 和所有工作都按预期工作。我有许多其他表没有任何 HierarchyId 列,并且这些表的创建操作都可以正常工作。

尽管如此,每次我尝试创建新项目或使用 HierarchyId 从表中查询现有项目时,都会收到一条错误提示

无法将“System.Int16”类型的对象转换为“System.String”类型

通过调试器中的步骤,我可以验证该值是否正确生成(在本例中为 /)并显示为类型 Microsoft.EntityFrameworkCore.HierarchyId,并且我还没有达到尝试序列化任何内容的地步还给客户,所以我不确定发生了什么。

使用的代码很简单(稍微概括一下):

var entity = new myTableItem
{
     myItemName = myItem.Name,
     myItemDescription = myItem.Description,
     myItemHierarchyId = HierarchyId.GetRoot()
}

myContext.add(entity);
myContext.save();

一旦到达Add,它就会爆炸并提供先前指定的错误。我也尝试过手动创建一个根,然后尝试通过它的 ID 检索根条目(DB Id 不是HierarchyId)所以我可以尝试添加一个子节点,但是一旦查询运行,我就会得到同样的错误而且它没有进一步发展(这就是我确定它是HierarchyId 列的方式)。作为参考,我用来检索根条目的代码如下:

parentItem = myContext.myTableItems.FirstorDefault(x => x.myItemId == myItem.myItemId).myItemHierarchyId

与创建一样,遍历调试器会显示一个返回的项目,该项目具有所有正确的属性和值,非常整洁,但它仍然会爆炸。日志内容,无论其价值如何,都包含在下面以供参考(概括类似于上面,但其他方面没有变化)。最后一行是我要转储到日志中的内容,因为这就是我一直使用 PowerShell 的方式,因为我今天早上才刚刚学会如何使用调试器进行基础操作,但它表明我拥有数据和正确的数据类型。

2021-09-13 12:28:54.0063 ERROR Something went wrong: Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
 ---> System.InvalidCastException: Unable to cast object of type 'System.Int16' to type 'System.String'.
   at Microsoft.Data.SqlClient.SqlBuffer.get_String()
   at Microsoft.Data.SqlClient.SqlDataReader.GetString(Int32 i)
   at lambda_method260(Closure , DbDataReader )
   at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeResultSetWithPropagation(Int32 commandIndex, RelationalDataReader reader)
   at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.Consume(RelationalDataReader reader)
   --- End of inner exception stack trace ---
   at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.Consume(RelationalDataReader reader)
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable`1 commandBatches, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IList`1 entries)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IList`1 entriesToSave)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(DbContext _, Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
   at MyProject.Repo.RepositoryManager.Save() in ..MyProject.Repo\RepositoryManager.cs:line 155
   at MyProcjet.API.Controllers.MyItemsController.NewMyItem(MyItemCreateDto MyItem) in ..MyItemsController.cs:line 181
   at lambda_method3(Closure , Object , Object[] )
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
2021-09-13 14:39:57.2496 INFO var myItemHierarchyId:/; Type: Microsoft.EntityFrameworkCore.HierarchyId

谁能帮忙?

【问题讨论】:

  • 我们能看到GetRoot()吗?
  • 我们可以看看myItem实体类吗?
  • GetRoot()的结果是'/',对象类型被识别为Microsoft.EntityFrameworkCore.HirearchyId。
  • ``` namespace MyProject.Entities { [Table("MyItems", Schema = "MyProject")] public class myTableItem { [Key] public int myItemId { get;放; } [必需] 公共字符串 myItemName { get;放; } 公共字符串 myItemDescription { 获取;放; } [必需] public HierarchyId myItemHierarchyId { get;放; } 公共字符串 myItemOrgLevel { 获取;放; } 公共字符串 myItemTextOrgLevel { 获取;放; } 公共日期时间? myItemCreated { 得到;放; } 公共日期时间? myItemModified { 得到;放; } } } ```

标签: c# asp.net-core ef-core-5.0 hierarchyid


【解决方案1】:

无法将“System.Int16”类型的对象转换为“System.String”类型

可能你的表中的列类型与myTableItem类中的类型不同。尝试检查你的myTableItem类和你的表,myTableItem类中的类型是int,表中是字符串。

【讨论】:

  • 数据库中的列类型显示为“hierarchyid,not null”。正如我所说,我不是开发人员,但问题似乎只是在将数据从 SQL 转换为 SQL 时才出现,因为每次弹出错误时,前两个值都是 'at Microsoft.Data.SqlClient.SqlBuffer.get_String ()' 和 'Microsoft.Data.SqlClient.SqlDataReader.GetString(Int32 i)'...在最长的时间里,我一直在查看以整数形式提交的其他道具,但后来我尝试了只查询记录和它弹出了同样的错误。根据我其他评论中的代码示例,该项目应该是 HierarchyId。
  • +1 您的 C# 模型在某处似乎有不正确的类型(与 hierarchyid 无关)。尝试scaffolding a model from the database 并将其与您的 DbContext 和实体类的外观进行比较。
  • @bricelam 您的建议恰到好处。在我的代码优先模型中,我将列定义为字符串,但无论出于何种原因,它都将该列创建为“small int”。当我为桌子搭建脚手架时,它把它设置为“短”。我没有注意到它,因为列值在数据库端自动生成,它不是我提交的内容的一部分。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-28
  • 2021-05-08
  • 2020-08-17
  • 1970-01-01
  • 1970-01-01
  • 2021-06-04
  • 2018-02-03
相关资源
最近更新 更多