2013-06-11 58 views
2

我下面從這裏忠告:獲取EF投影時間跨度屬性轉換時間跨度從蜱

What is the correct SQL type to store a .Net Timespan with values > 24:00:00?

裏面一個名爲TimesheetEntry我有模式:

public Int64 NetLengthTicks { get; set; } 

[NotMapped] 
public TimeSpan NetLength 
{ 
    get { return TimeSpan.FromTicks(NetLengthTicks); } 
    set { NetLengthTicks = value.Ticks; } 
} 

我試圖這樣:

var shiftsData = from shift in filteredShifts 
       where shift.IsDeleted == false 
       select new 
       { 
        shift.TimesheetShiftId, 
        shift.UserId, 
        shift.HasShiftEnded, 
        shift.StartTime, 
        shift.EndTime, 
        Entries = from entry in shift.Entries 
          where entry.IsDeleted == false 
          select new 
          { 
           entry.TimesheetEntryId, 
           entry.TimesheetShiftId, 
           entry.EntryType, 
           entry.StartTimeSpan, 
           entry.NetLength, 
          } 
       }; 

我得到的例外:

The specified type member 'NetLength' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported. 

我試圖改變投射到:

NetLength = TimeSpan.FromTicks(entry.NetLengthTicks) 

但給了異常:

LINQ to Entities does not recognize the method 'System.TimeSpan FromTicks(Int64)' method, and this method cannot be translated into a store expression. 

然後我試圖創建一個表達式來執行轉換:

public static Expression<Func<DAL.Models.TimesheetEntry, TimeSpan>> NetLengthExpression 
{ 
    get 
    { 
     return e => TimeSpan.FromTicks(e.NetLengthTicks); 
    } 
} 

// in the projection 
NetLength = NetLengthExpression 

但是扔了:

The LINQ expression node type 'Lambda' is not supported in LINQ to Entities. 

有沒有辦法揭露NetLength在我的查詢應退時間跨度?

回答

1

除非EF知道如何進行轉換,否則您將無法在數據庫端執行轉換,而且聽起來像EF不知道如何執行此轉換。

您將不得不使用助手方法進行轉換。

我通常在我的DataContext類中使用幫助器方法來處理這種情況,因爲如果我正在執行查詢,那麼通常會有該類的一個實例來處理。

public class DataContext : DbContext { 
    public TimeSpan GetTimeSpan(Int64 ticks) { 
     return TimeSpan.FromTicks(ticks); 
    } 

    // ... other code 
} 

編輯

這也可能是一個選項:

var shiftsData = from shift in filteredShifts 
       where shift.IsDeleted == false 
       select new 
       { 
        shift.TimesheetShiftId, 
        shift.UserId, 
        shift.HasShiftEnded, 
        shift.StartTime, 
        shift.EndTime, 
        Entries = from entry in shift.Entries 
          where entry.IsDeleted == false 
          select entry 
       }; 

如果你擺脫你的查詢創建匿名類的,只是select entry,你會得到一個實例你的Entry類,它將填充你的NetLengthTicks屬性,並讓你使用你的NetLength吸氣劑。但請注意,如果您投影類的實例,則可能會選擇比實際所需更多的行。

+1

這與我現有的包裝屬性沒有任何區別。在我的投影中使用GetTimeSpan方法拋出:LINQ to Entities無法識別方法'System.TimeSpan GetTimeSpan(Int64)'...我知道轉換在查詢解決後工作,但我試圖在因爲我將在一組班中返回一組條目。對結果執行嵌套的ForEach並對結果應用轉換是緩慢和難看的。 – mbursill

+0

@mbursill - 但是你沒有'E​​ntry'的實例,因爲你正在用查詢創建一個匿名類,所以如果不實例化一個'Entry'實例就不能使用wrapper屬性。如果你改變'select new ...''選擇條目',你會得到'Entry'類的一個實例,並且你可以使用'NetLength'屬性。但是這樣做可能會返回比您真正需要的更多的行。 – ken