2015-06-24 34 views
10

!!!請不要重定向到this article,因爲它不能解決下面描述的問題。LINQ2SQL:如何在加載匿名實體時修改字段值?

比方說,我們在數據庫中有這樣的表:

SomeTable

  • ID(INT)
  • DT(日期時間)

我們已經配置了一個LINQ2SQL數據上下文。並且我們已經爲SomeTable配置了一個實體:OnLoaded方法修改了DT,使DT的DateTimeKind成爲Utc(最初是Unspecified)。

現在,這裏的問題是:

如果我們用整個實體請求數據時,裝載的方法被稱爲:

From x In ourDataContext.SomeTable Select x 

但是,如果我們只請求表的一部分(並因此產生一個匿名型),將裝載的不叫:

From x In ourDataContext.SomeTable Select x.DT 

很清楚,裝載的是SomeTable實體定義,而不是匿名類型。

目前我考慮創建將取代匿名類型的自定義實體。但也許有人有更好的解決方案?

回答

1

我們有類似的問題,因爲我們需要從實體接收部分字段作爲匿名對象,並且始終知道我們有日期字段的DateTimeKind作爲DateTimeKind.UTC而不使用LINQ請求中的附加功能。

我們嘗試了很多東西,但是我們發現只有一個足夠好的解決方案 - 使用T4爲Linq2Sql生成代碼。

P.S.如果您想了解更多關於使用T4生成Linq2Sql代碼的信息,您可以從http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx

+0

我想這是現​​在唯一的方法...:/ – Dima

0

你可以指定查詢中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() 
+0

開始,這打破了將功能委託給Linq2Sql的想法。如果某些開發人員忘記使用AsUtc,那麼他將收到不正確的數據。 – Dima

3

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在這裏提供了一些靈活性(如上所示),但如果解決方案不令人滿意,還有其他選擇:

  1. L2S DAL上方的顯式層。通常情況下,它是一個存儲庫模式 ,它返回的DTO非常類似於L2S自動生成的DTO。在這種情況下,您可以隱藏DT財產,強制消費者僅使用CustomDT
  2. 將邏輯放入數據庫(視圖,計算列,SP)。 I 不會將這種方法用於新項目,但它可能是某些傳統應用程序的可行選項。
+0

這種方法在問題中有所描述,但我正在尋找更好的方法。 – Dima

+0

我看不出問題如何描述使用額外的屬性來解決您的問題。它適用於投影(如示例)和選擇場景。 – UserControl

+0

好吧,很簡單:我們必須引入自定義代碼,這有兩個缺點: 1.第三方開發者仍然不能直接使用DT屬性(因此整個自動DT屬性的想法被打破) 2.使用CustomDT在查詢中,LINQ2SQL跳過優化:它從數據庫請求所有表字段,而不是隻請求DT字段。 – Dima

0

您可以使用linq-to-sql的查詢部分,並使用linq-to-objects抓住你想要的屬性DateTime(你實際上並沒有返回一個匿名類型)。

(From x In ourDataContext.SomeTable _ 
Select x).AsEnumerable() _ 
      .Select(Function(x) x.DT) 
0

你可以試試這段代碼嗎?您可以指定相同的表類型,但只加載一個字段,而不使用匿名類型。我不知道你的情況是否會起作用。

SomeTable.Select(x => new SomeTable { 
    DateField = x.DateField 
}) 

否則沒有簡單的解決方案。

相關問題