将现有数据库映射到 EF 的数据类型不匹配
Datatype mismatch mapping existing database to EF
我正在使用现有的生产数据库来创建 MVC 应用程序,但由于数据类型不匹配,我无法正确设置父级的虚拟属性 class。我的代码如下:
public class bill {
public int billId { get; set; }
.........
}
public class meter {
public int meterId { get; set; }
public int billId { get; set; }
.....
}
public class payment {
public int paymentId { get; set; }
public long billId { get; set; }
......
}
我在账单中添加了以下内容class:
public virtual ICollection<meter> Meters { get; set; }
public virtual ICollection<payment> Payments { get; set; }
我能够检索相关的仪表,但由于支付中的 billid
长数据类型,我收到了一个错误。在我对代码优先模型的更改不影响原始数据库的情况下,是否有任何方法可以正确映射它?
我收到错误:
Invalid column name 'bill_billId'.
Invalid column name 'bill_billId'.
Invalid column name 'bill_billId'.
当尝试显示如下:
@foreach (var m in Model.Meters.Where(x => x.archived != true && x.meterUnitsUsed > 0))
{
<tr>
<td>@Html.DisplayFor(x => m.meterSerialNumber)</td>
<td>@Html.DisplayFor(x => m.meterOpeningRead)</td>
<td>@Html.DisplayFor(x => m.meterClosingRead)</td>
<td>@Html.DisplayFor(x => m.meterUnitsUsed)</td>
<td>@Html.DisplayFor(x => m.archived)</td>
<td>@Html.DisplayFor(x => m.meterUnitType)</td>
<td>@Html.DisplayFor(x => m.meterUnitPrice)</td>
<td>@Html.DisplayFor(x => m.meterAmount)</td>
@foreach (var i in Model.LiftsRefunds.Where(i => i.archived != true))
{
<td>@Html.DisplayFor(x => i.liftRefundDate)</td>
<td>@Html.DisplayFor(x => i.liftRefundAmount)</td>
<td>@Html.DisplayFor(x => i.liftType)</td>
}
</tr>
}
当前使用的数据库设置不正确,子 class 使用 long 数据类型,而父 class 的主键是 int。是否有任何方法可以设置 EF 忽略它并将 long 映射到 int 以便可以将付款引用为虚拟属性?
错误:
The 'billId' property on 'payment' could not be set to a 'System.Int64' value. You must set this property to a non-null value of type 'System.Int32'
按照说明进行操作 here:
In your EDMX, if you go under your Y table and click on X column, right-click, click on Properties, scroll down to Nullable and change from False to True.
If you get a "mapping fragment" error, you'll have to delete the table from the EDMX and re-add it, because in the Model Browser it stores the table properties and the only way to refresh that (that I know of) is to delete the table from the Model Browser under .Store then retrieving it using Update Model from Database.. command.
更多信息,请参阅 MSDN 文档:How to: Update an .edmx File when the Database Changes (Entity Data Model Tools)
我认为您有 2 个不同的问题。
===
首先,payment.billId
是对 bill.billId
的引用,我们假设它们在 SQL 服务器上有 2 个不同的列(每个 table 一个)。
1. 如果你忽略迁移(实际上你忽略了迁移并且没问题)如果 SQL 服务器中的数据类型与 classes 的数据类型不同,即 int 和 bigint,你的程序也会工作在 SQL 服务器上,int 和 int 在你的 classes.
2. 但是 SQL 服务器无法建立从 bigint 列到 int 列的关系,因此在您的数据库中,您不能将 bigint 和 int 用于两列,或者您没有关系(您没有必须,EF 无论如何都会工作,但这不是一个好习惯)。
所以我建议你检查你在 SQL 服务器上做什么,然后更改 classes 的数据类型(即设置所有 int)并禁用迁移。
===
现在,为什么关于不存在字段的错误?
在您的 classes 中,您遇到了映射配置问题。
您必须将 payment.billId
属性 与 public virtual ICollection<payment> Payments { get; set; }
连接起来。
我使用流畅的映射和每个 class 一个映射文件,所以在这种情况下,在付款的映射文件中我写
HasRequired(t => t.bill)
.WithMany(t => t.Payments)
.Map(d => d.MapKey("billId"));
您可以对属性执行相同的操作。
我正在使用现有的生产数据库来创建 MVC 应用程序,但由于数据类型不匹配,我无法正确设置父级的虚拟属性 class。我的代码如下:
public class bill {
public int billId { get; set; }
.........
}
public class meter {
public int meterId { get; set; }
public int billId { get; set; }
.....
}
public class payment {
public int paymentId { get; set; }
public long billId { get; set; }
......
}
我在账单中添加了以下内容class:
public virtual ICollection<meter> Meters { get; set; }
public virtual ICollection<payment> Payments { get; set; }
我能够检索相关的仪表,但由于支付中的 billid
长数据类型,我收到了一个错误。在我对代码优先模型的更改不影响原始数据库的情况下,是否有任何方法可以正确映射它?
我收到错误:
Invalid column name 'bill_billId'.
Invalid column name 'bill_billId'.
Invalid column name 'bill_billId'.
当尝试显示如下:
@foreach (var m in Model.Meters.Where(x => x.archived != true && x.meterUnitsUsed > 0))
{
<tr>
<td>@Html.DisplayFor(x => m.meterSerialNumber)</td>
<td>@Html.DisplayFor(x => m.meterOpeningRead)</td>
<td>@Html.DisplayFor(x => m.meterClosingRead)</td>
<td>@Html.DisplayFor(x => m.meterUnitsUsed)</td>
<td>@Html.DisplayFor(x => m.archived)</td>
<td>@Html.DisplayFor(x => m.meterUnitType)</td>
<td>@Html.DisplayFor(x => m.meterUnitPrice)</td>
<td>@Html.DisplayFor(x => m.meterAmount)</td>
@foreach (var i in Model.LiftsRefunds.Where(i => i.archived != true))
{
<td>@Html.DisplayFor(x => i.liftRefundDate)</td>
<td>@Html.DisplayFor(x => i.liftRefundAmount)</td>
<td>@Html.DisplayFor(x => i.liftType)</td>
}
</tr>
}
当前使用的数据库设置不正确,子 class 使用 long 数据类型,而父 class 的主键是 int。是否有任何方法可以设置 EF 忽略它并将 long 映射到 int 以便可以将付款引用为虚拟属性?
错误:
The 'billId' property on 'payment' could not be set to a 'System.Int64' value. You must set this property to a non-null value of type 'System.Int32'
按照说明进行操作 here:
In your EDMX, if you go under your Y table and click on X column, right-click, click on Properties, scroll down to Nullable and change from False to True.
If you get a "mapping fragment" error, you'll have to delete the table from the EDMX and re-add it, because in the Model Browser it stores the table properties and the only way to refresh that (that I know of) is to delete the table from the Model Browser under .Store then retrieving it using Update Model from Database.. command.
更多信息,请参阅 MSDN 文档:How to: Update an .edmx File when the Database Changes (Entity Data Model Tools)
我认为您有 2 个不同的问题。
===
首先,payment.billId
是对 bill.billId
的引用,我们假设它们在 SQL 服务器上有 2 个不同的列(每个 table 一个)。
1. 如果你忽略迁移(实际上你忽略了迁移并且没问题)如果 SQL 服务器中的数据类型与 classes 的数据类型不同,即 int 和 bigint,你的程序也会工作在 SQL 服务器上,int 和 int 在你的 classes.
2. 但是 SQL 服务器无法建立从 bigint 列到 int 列的关系,因此在您的数据库中,您不能将 bigint 和 int 用于两列,或者您没有关系(您没有必须,EF 无论如何都会工作,但这不是一个好习惯)。
所以我建议你检查你在 SQL 服务器上做什么,然后更改 classes 的数据类型(即设置所有 int)并禁用迁移。
===
现在,为什么关于不存在字段的错误?
在您的 classes 中,您遇到了映射配置问题。
您必须将 payment.billId
属性 与 public virtual ICollection<payment> Payments { get; set; }
连接起来。
我使用流畅的映射和每个 class 一个映射文件,所以在这种情况下,在付款的映射文件中我写
HasRequired(t => t.bill)
.WithMany(t => t.Payments)
.Map(d => d.MapKey("billId"));
您可以对属性执行相同的操作。