在 属性 中首先编码存储函数

Code first Store Functions in a Property

我在尝试将数据库中的字符串列映射到我的应用程序中的整数时遇到问题。

我有一个包含车辆集合的数据库,创建 table 时,年份列被指定为 varchar。我需要该值作为整数才能用它执行计算。

我知道我可以使用 int.Parse 来转换它,但我需要它在 entity framework 查询中工作。 int.Parse 在 linq to entities 中不受支持,因此该方法已过时。

我尝试的下一件事是创建视图并将列转换为 int。这工作得很好,直到我需要写入数据库,然后抛出错误,因为视图包含派生字段。

接下来我尝试使用 Pawel Kadluczka 的 "EntityFramework.CodeFirstStoreFunctions" 库。这确实有效,但只有当我像这样直接指定它时才有效:

Store.Vehicles.Where(x => CustomSqlFunctions.ParseInt(x.ModelYear) == 2000)

其中 ParseInt 在 c# 中定义为

[CodeFirstDbFunction("ParseInt")]
public static int ParseInt(string number) {
    throw new NotSupportedException("Direct calls are not supported.");
}

sql 中的 ParseInt 函数只是调用 cast( @p1 as int),其中 @p1 是传入的字符串。

我的问题是:
是否可以从 Vehicle class 中的 属性 中调用 CustomSqlFunctions.ParseInt(ModelYear)

我试过这个:

public int? Year {
    get { return CustomSqlFunctions.ParseInt(ModelYear); }
    set { ModelYear = value.ToString(); }
}

但我收到错误消息,指出 LINQ to Entities 不支持年份

我假设 Year 没有映射到数据库。在这种情况下,您可以这样做等效的 "cast":

get
{
    int value;
    return int.TryParse(ModelYear, out value) ? value : null;
}

我终于明白了。这是一个相当简单的解决方案。我返回到带有计算列的自定义视图。然而,这一次,我保留了名为 'ModelYear' 的原始字段,并添加了 'Year' 列,该列将从字符串转换为 int。

属性 年最终是这样的:

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public int? Year {
    get { return _year; }
    set {
        _year = value;
        ModelYear = value.ToString();
    }
}

当一个值设置为 Year 时,它也作为字符串设置为 ModelYear。当模型保存到数据库时,ModelYear 字段会更新,并且由于 Year 字段被标记为已计算,框架不会尝试保存该字段。

作为旁注实际上并没有开始调用 Year。在单步执行 Entity framework 的源代码后,我发现在计算表达式之前,它首先检查被调用的 属性 是否实际上是数据库中的映射成员。由于 Year 未映射,因此甚至未对包含 Year 的表达式求值。