有没有办法找出哪个表列导致与实体框架的转换出错?
Posted
技术标签:
【中文标题】有没有办法找出哪个表列导致与实体框架的转换出错?【英文标题】:Is there a way to find out which table column is causing an error in conversion with Entity Framework? 【发布时间】:2021-10-13 07:22:56 【问题描述】:我有一个简单的 MVC 应用程序,它使用我的 API 通过实体框架 DbContext 在 SQL Server DB 中注册信息。
我可以将应用程序中的实体注册到数据库中。但是,每当我尝试从数据库中检索它以在我的应用程序中显示它时,我都会收到一个 System.InvalidCastException
向我抛出的消息,并且它携带的消息并不是非常有用,它只是说“指定的转换无效”。 .尝试执行context.MyTable.ToList()
时抛出异常。
我已经查看了我的模型,但我没有看到任何类型不匹配,并且我使用 fluentAPI 来处理 bool
和 bit
之间的转换,所以我怀疑是那个字段(我有一个不同的应用程序,其中问题没有发生,我使用该方法来处理布尔值)
这是我的表的代码:
Create table Property(
Id int IDENTITY (1,1) PRIMARY KEY,
Description varchar(60) not null,
SalesPrice decimal(18,2) not null,
Building bit not null,
ZoningClass varchar(1) not null,
Profit decimal(18,2),
ImgPath varchar(300)
)
型号:
public class Property
[Key]
[DisplayName("Prop ID")]
[Column("Id", TypeName="int")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id get; set;
[DisplayName("Property Description")]
[Required(ErrorMessage = "Description cannot be empty.")]
[Column("Description", TypeName="varchar(60)")]
[StringLength(60, ErrorMessage = "Description cannot be over 60 characters.")]
public string Description get; set;
[Required(ErrorMessage = "Sales price cannot be empty")]
[Range(0, double.MaxValue, ErrorMessage ="Sales price cannot be negative.")]
[DisplayName("Sales Price ($)")]
[Column("SalesPrice", TypeName ="decimal(18,2)")]
public decimal SalesPrice get; set;
[Required]
[DisplayName("Property has building.")]
[Column("Building")]
public bool Building get; set;
[Required(ErrorMessage = "Specify a Zoning class")]
[DisplayName("Zoning Class")]
[Column("ZoningClass", TypeName ="varchar(1)")]
public string ZoningClass get; set;
[Column("Profit", TypeName = "decimal(18,2)")]
public decimal Profit get; set;
[Required(ErrorMessage = "Indicate Image Route")]
[StringLength(300, ErrorMessage = "Route cannot be over 300 characters")]
[Column("ImgPath", TypeName = "varchar(300)")]
public string ImgPath get; set;
处理注册到数据库的控制器方法:
[HttpPost]
public ActionResult Register(Property model)
model.Profit = 0;
if (ModelState.IsValid)
switch (model.ZoningClass)
case "A":
model.Profit = model.SalesPrice * (decimal)0.05;
break;
case "B":
model.Profit = model.SalesPrice * (decimal)0.04;
break;
case "C":
model.Profit = model.SalesPrice * (decimal)0.03;
break;
default:
model.Profit = 0;
break;
//requestHandler simply sends an HTTP request to the API.
var res = requestHandler.AddProperty(model);
if(res.StatusCode == HttpStatusCode.Created)
TempData["Created"] = "Client Created";
return View("CreateProperty", new Property());
return View("CreateProperty", model);
以及 DbContext 本身
public class PropertyContext : DbContext
public DbSet<Property> Property get; set;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
optionsBuilder.UseSqlServer(@"Server=myserver;Database=mydb; User Id=myuser; Password=mypass;");
protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.Entity<Property>().
Property(p => p.Building).
HasConversion(
v => v ? 1 : 0,
v => (v == 1)
);
因此,模型中的字段与表中的列之间似乎存在正确的对应关系。我看不出是哪一个导致了错误,并且调试应用程序对我没有帮助,因为异常本身对我来说不是很易读。
【问题讨论】:
SqlClient 中有一个突出的错误,它将无法转换某些decimal
值。见github.com/dotnet/SqlClient/issues/95
我在您发布的实际代码中的任何地方都看不到context.MyTable.ToList()
。能贴出实际抛出异常的方法吗?
我没有包含它,因为它实际上就是这样做的,它使用 using 语句和上下文打开连接,然后只执行 context.Property.ToList();
那么为什么要进行转换?布尔值自动映射到位字段,即 0 或 1。
我不知道这种隐式转换,对于以前的应用程序我也有类似的问题。在以前的应用程序中,问题最终是由其他原因引起的,但我仍然将转换留在那里以防万一。无论如何,那段代码是处理值转换的有效流利的 api 代码,所以它真的不应该是一个问题。
【参考方案1】:
尝试删除已转换。没见过有人用过
modelBuilder.Entity<Property>().
Property(p => p.Building).
HasConversion(
v => v ? 1 : 0,
v => (v == 1)
);
如果你需要一些特别的东西,最好把代码放在 get;设置;
您的相关要求也太多了。例如 [Required(ErrorMessage = "销售价格不能为空")]。它永远不会为空,因为它不可为空,因此永远不会被触发。 您只能使用 [Range(0, double.MaxValue, ErrorMessage ="销售价格不能为空,应为正数。")]。或列名称,因为它们与属性名称相同。
根据 sql 脚本,Profit 列可能为空,恕我直言,属性也应该可以为空
public decimal? Profit get; set;
【讨论】:
bitbool 转换内置于 SqlClient:docs.microsoft.com/en-us/dotnet/framework/data/adonet/… 是的,你是对的。我认为在这里使用它没有任何意义。特别是如果它引起问题 正如我在帖子中指出的那样:这不是转换,因为我有另一个应用程序使用该确切的代码位,并且对于在此应用程序中引发异常的相同操作执行良好。 试试吧。如果您不需要,最好现在将其删除,以后不要使用。 删除后什么也没做。我知道这段代码可能无关紧要,但它也不是导致问题的原因,这是使用 fluent api 处理转换的有效语法。我现在的猜测是,由于控制器中发生了十进制乘法,问题正在发生。它最有可能改变数字的精度。【参考方案2】:在您的数据库中,Profit
可以为空,因为您没有设置 not null
,因此您的属性必须可以为空。改成
public decimal? Profit get; set;
【讨论】:
以上是关于有没有办法找出哪个表列导致与实体框架的转换出错?的主要内容,如果未能解决你的问题,请参考以下文章
实体框架,如何将 IQueryable 与多个 where 转换为 SQL 一起使用?
有没有办法避免在我的 UI 项目中添加对实体框架的引用而不使用 Web 服务作为中间人?
找出在 UIActivityViewController 中单击了哪个图标
将 mogenerator 与 Core Data 实体一起使用会导致保存数据存储时出错