LINQ2SQL:加载匿名实体时如何修改字段值?
LINQ2SQL: How to modify fields values when loading anonymous entities?
!!!请不要重定向到 this article,因为它不能解决下面描述的问题。
假设我们在数据库中有这样的table:
SomeTable
- ID(整数)
- DT(日期时间)
我们已经配置了 Linq2Sql 数据上下文。我们为 SomeTable 配置了一个实体:OnLoaded 方法修改 DT,使 DT 的 DateTimeKind 变为 Utc(最初它是未指定的)。
现在问题来了:
如果我们使用整个实体请求数据,调用OnLoaded方法:
From x In ourDataContext.SomeTable Select x
但是如果我们只请求 table 的一部分(因此生成匿名类型),则不会调用 OnLoaded:
From x In ourDataContext.SomeTable Select x.DT
很明显OnLoaded是在SomeTable实体中定义的,而不是匿名类型。
目前我正在考虑创建自定义实体来替换匿名类型。但也许有人有更好的解决方案?
您可以在查询中指定 DateTimeKind
:
from x in ourDataContext.SomeTable
select DateTime.SpecifyKind(x.DT, DateTimeKind.Utc)
如果您经常这样做,扩展方法可能有助于减少冗长:
public static class Ext
{
public static DateTime AsUtc(this DateTime dateTime)
{
return DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
}
public static DateTime? AsUtc(this DateTime? dateTime)
{
if(dateTime == null) return null;
return AsUtc(dateTime.Value);
}
}
那么您的查询变为:
from x in ourDataContext.SomeTable select x.DT.AsUtc()
Linq2Sql 为表生成部分 类,因此非常容易扩展。只需将 SomeTable.cs
文件添加到您的解决方案中(在与自动生成的数据库上下文相同的命名空间内)并定义一个额外的 属性 以及您需要的任何行为:
public partial class SomeTable {
public System.DateTime CustomDT {
get { return DT.AddYears(120); }
}
}
现在可以正常查询了:
var e = ctx.SomeTable.Select(x => new { x.CustomDT }).First();
Console.WriteLine(e.CustomDT);
更新:
根据评论,我认为您面临的问题是由于职责分离不正确造成的。您正在尝试将业务逻辑(数据转换)责任传递给您的 DAL。虽然 L2S 在这里提供了一些灵活性(如上所示),但如果解决方案不令人满意,您还有其他选择:
- L2S DAL 之上的显式层。通常它是一个存储库模式
returns DTO 与 L2S 自动生成的非常相似。在这种情况下,您可以隐藏
DT
属性 强制消费者仅使用 CustomDT
。
- 将逻辑放入数据库(视图、计算列、SP)。我
不会考虑将这种方法用于新项目,但它可能是
一些遗留应用程序的可行选择。
您可以使用 linq-to-sql
作为查询部分,并使用 linq-to-objects
获取您想要的 DateTime
属性(您实际上并没有返回匿名类型)。
(From x In ourDataContext.SomeTable _
Select x).AsEnumerable() _
.Select(Function(x) x.DT)
你能试试这个代码吗?您可以指定相同的 Table 类型,但只加载一个字段,而不是使用匿名类型。我不知道它是否适用于你的情况。
SomeTable.Select( x => new SomeTable {
DateField = x.DateField
})
否则没有简单的解决办法
我们遇到了类似的问题,因为我们需要从实体接收部分字段作为匿名对象,并且始终知道我们有 DateTimeKind
个日期字段作为 DateTimeKind.UTC
,而无需在 LINQ 请求中使用其他函数。
我们尝试了很多东西,但我们只找到了一个足够好的解决方案 - 使用 T4 为 Linq2Sql 生成代码。
P.S.如果想了解更多关于使用T4生成Linq2Sql代码,可以从http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx
开始
!!!请不要重定向到 this article,因为它不能解决下面描述的问题。
假设我们在数据库中有这样的table:
SomeTable
- ID(整数)
- DT(日期时间)
我们已经配置了 Linq2Sql 数据上下文。我们为 SomeTable 配置了一个实体:OnLoaded 方法修改 DT,使 DT 的 DateTimeKind 变为 Utc(最初它是未指定的)。
现在问题来了:
如果我们使用整个实体请求数据,调用OnLoaded方法:
From x In ourDataContext.SomeTable Select x
但是如果我们只请求 table 的一部分(因此生成匿名类型),则不会调用 OnLoaded:
From x In ourDataContext.SomeTable Select x.DT
很明显OnLoaded是在SomeTable实体中定义的,而不是匿名类型。
目前我正在考虑创建自定义实体来替换匿名类型。但也许有人有更好的解决方案?
您可以在查询中指定 DateTimeKind
:
from x in ourDataContext.SomeTable
select DateTime.SpecifyKind(x.DT, DateTimeKind.Utc)
如果您经常这样做,扩展方法可能有助于减少冗长:
public static class Ext
{
public static DateTime AsUtc(this DateTime dateTime)
{
return DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
}
public static DateTime? AsUtc(this DateTime? dateTime)
{
if(dateTime == null) return null;
return AsUtc(dateTime.Value);
}
}
那么您的查询变为:
from x in ourDataContext.SomeTable select x.DT.AsUtc()
Linq2Sql 为表生成部分 类,因此非常容易扩展。只需将 SomeTable.cs
文件添加到您的解决方案中(在与自动生成的数据库上下文相同的命名空间内)并定义一个额外的 属性 以及您需要的任何行为:
public partial class SomeTable {
public System.DateTime CustomDT {
get { return DT.AddYears(120); }
}
}
现在可以正常查询了:
var e = ctx.SomeTable.Select(x => new { x.CustomDT }).First();
Console.WriteLine(e.CustomDT);
更新:
根据评论,我认为您面临的问题是由于职责分离不正确造成的。您正在尝试将业务逻辑(数据转换)责任传递给您的 DAL。虽然 L2S 在这里提供了一些灵活性(如上所示),但如果解决方案不令人满意,您还有其他选择:
- L2S DAL 之上的显式层。通常它是一个存储库模式
returns DTO 与 L2S 自动生成的非常相似。在这种情况下,您可以隐藏
DT
属性 强制消费者仅使用CustomDT
。 - 将逻辑放入数据库(视图、计算列、SP)。我 不会考虑将这种方法用于新项目,但它可能是 一些遗留应用程序的可行选择。
您可以使用 linq-to-sql
作为查询部分,并使用 linq-to-objects
获取您想要的 DateTime
属性(您实际上并没有返回匿名类型)。
(From x In ourDataContext.SomeTable _
Select x).AsEnumerable() _
.Select(Function(x) x.DT)
你能试试这个代码吗?您可以指定相同的 Table 类型,但只加载一个字段,而不是使用匿名类型。我不知道它是否适用于你的情况。
SomeTable.Select( x => new SomeTable {
DateField = x.DateField
})
否则没有简单的解决办法
我们遇到了类似的问题,因为我们需要从实体接收部分字段作为匿名对象,并且始终知道我们有 DateTimeKind
个日期字段作为 DateTimeKind.UTC
,而无需在 LINQ 请求中使用其他函数。
我们尝试了很多东西,但我们只找到了一个足够好的解决方案 - 使用 T4 为 Linq2Sql 生成代码。
P.S.如果想了解更多关于使用T4生成Linq2Sql代码,可以从http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx
开始