2013-07-01 62 views
3

有什麼方法可以爲Linq2Entities的附加功能定義SQL轉換組件。添加新的方法到LINQ to Entities

例如:

myQuery.Where(entity => entity.Contains('foo', SearchFlags.All)) 

理想我要尋找的東西,不需要編輯,並直接建立一個新版本的EntityFramework.dll。有什麼辦法讓擴展方法可以支持SQL生成的實體框架。

到目前爲止,我有這將意味着我需要爲LINQ更換給實體的方法的模板:

public static bool Contains(this object source, string searchTerms, SearchFlags flags) 
{ 
    return true; 
} 

當然,這將導致錯誤:

LINQ to Entities does not recognize the method 'Boolean CONTAINS(System.Object, System.String, SearchFlags)' method, and this method cannot be translated into a store expression.

要清楚,我不想做:

myQuery.AsEnumerable().Where(entity => entity.Contains('foo', SearchFlags.All)) 

因爲我想能夠在SQL空間中執行代碼而不是r手動刪除所有實體。

我也不能使用IQueryable.ToString()並手動執行它,因爲我需要實體框架來填充幾個.Include連接的對象。

+1

「* Model-declared functions *」(http://msdn.microsoft.com/en-us/library/ee382839.aspx)或「* Model-defined functions *」(http://msdn.microsoft.com/en-us/library/default.aspx)。 com/en-us/library/ee382833.aspx)可能是您可以嘗試的一種方法。 Code-First不支持這兩種工具,只有基於EDMX的工作流(DB-First或Model-First),後者需要使用不具有所有SQL功能的實體SQL。 – Slauma

+0

@Slauma看起來很有用,但是我堅持使用代碼優先,我可以用它們來爭辯我們應該先使用DB-first,因爲我們無論如何都要將DB分開管理DB – Seph

+0

您運行的代碼是針對哪種SQL Server版本的? – Marcel

回答

0

最後我做了以下(工作,但遠非完美):

  1. 我所有的實體從IEntity定義long Id { get; set; }
  2. 我加入了冗餘限制 context.myEntities.Where(entity => entity.Id != 0)這是 多餘的,因爲身份開始於1繼承,但Linq2Entities不 知道。
  3. 我然後調用.ToString()IQueryable我已經做了所有我 其他查詢後,因爲它是DBQuery<Entity>返回 SQL命令文本類型的,我做一個簡單的與我的查詢限制更換。
  4. 爲了讓所有的.Include(...)工作,我實際上執行了 兩個不同的sql命令。由於查詢執行計劃緩存導致其他問題(甚至在禁用時),因此沒有其他更好的方法可以使用它。

結果我的代碼看起來是這樣的:

public IQueryable<IEntity> MyNewFunction(IQueryable<IEntity> myQueryable, string queryRestriction) 
{ 
    string rawSQL = myQueryable.Select(entity => entity.Id).ToString().Replace("[Extent1].Id <> 0", queryRestriction); 
    List<long> ids = // now execute rawSQL, get the list of ids; 
    return myQuerable.Where(entity => ids.Contains(entity.Id)); 
} 

總之,除了手動執行SQL或運行類似SQL命令,並使用現有的命令的唯一的方式來寫附加限制你自己的Linq-to-Entities方法是從EF6源手動修改和構建你自己的EntityFramework.dll。

0

我不明白你的Q值。但是,如果你的問題是你不能使用你自己的方法或其他的LINQ to對象的方法,只是使用.AsEnumerable(),做你的其他工作,通過LINQ到對象,而不是L2E:

myQuery.AsEnumerable().Where(entity => entity.Contains('foo', SearchFlags.All)) 

如果你需要使用您myQuery幾次別的地方,首先將其加載到內存中,然後用它多達你想要的:

var myQuery = from e in context.myEntities 
       select d; 
myQuery.Load(); 

// ... 

var myOtherQuery = from d in context.myEntities.Local       
        select d; 
        // Now any L2O method is supported... 
+0

這個建議是否合理在他的問題中說:「要清楚,我不想這樣做......'AsEnumerable()'... *」? – Slauma

+0

@Slauma - 我沒有看到。所以他可以用第二個......他不能......?!我錯了嗎...?!!! – AminSaghi

+0

它與'AsEnumerable'基本相同(將未過濾的數據加載到內存中)。我想他只是不想將整個表格(可能有數百萬條記錄)加載到內存中並在那裏過濾。 – Slauma