我有一个使用Code First Entity Framework的MVC应用程序。
我的数据库中有记录字符串的序列号,以及字母和数字的组合。 最后4个始终是数字部分。
我正在尝试检索范围A和B之间的所有记录,例如从 SERIAL-NO-0020 到 SERIAL-NO-0050
我无法将字符串数字部分转换为整数,因为Linq To Entities不支持它。因此,作为获取序列号高于20的所有记录的示例,这不起作用:
var records = context.SerialNumbers.Where(m => Convert.ToDecimal(m.SerialNo.Substring(10, 4)) > 20).ToList();
有没有办法在没有先从数据库中提取所有记录并进一步过滤的情况下执行此操作?
答案 0 :(得分:1)
您可以在Linq的帮助下编写SP并访问此SP(存储过程),而不是编写查询。 在SP中,您可以先拆分记录然后进行比较。它也将花费更少的时间并提高性能。
答案 1 :(得分:1)
Convert.ToDecimal
无法转换为SQL。
您可以创建一个查询数据的存储过程,以便您可以执行不能由EF完成的任何操作。
另一种解决方案是创建一个计算列。
首先,添加新属性。我们在SerialId
实体中为其命名SerialNumber
。
第二次,使用数据注释装饰该属性:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
或根据需要使用流畅的配置:
modelBuilder.Entity<SerialNumber>().Property(t => t.SerialId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
第三次,添加新的EF迁移,并在生成的迁移文件中,只需将新值传递给下面的defaultValueSql
参数列表来更新它:
public override void Up()
{
AddColumn(
"dbo.SerialNumber",
"SerialId",
c => c.Int(nullable: false, defaultValueSql: "CAST(SUBSTRING(SerialNo, 11, 4) AS INT)"));
}
修改说SerialNumber
表的每一行都有一个生成的列,并且使用此SQL语句计算其值=&gt; CAST(SUBSTRING(SerialNo, 11, 4) AS INT)
您可以通过运行ef command =&gt;来更新数据库update-databse
。
最后,您可以将Linq更改为如下所示的实体,并且您不需要任何转化:
var records = context.SerialNumbers.Where(m => m.SerialId > 20).ToList();