2012-03-18 57 views
0

小EF問題。 我在EF中映射了多對多關係。 X.Y 所以當我有一個X有一個屬性X.Ys.實體框架代碼優先 - 多對多過濾

現在我想要做的是使用LINQ查詢得到一些X的,但我不希望有所有的Y的選擇X的內部。 我想Y's過濾Y.RegistrationDate> Date.Today。

所以,當我有一個X,並通過.Y's,我只會得到未來的Y's。

UPDATE 這工作,導致S中有與它的關係只包含即將舉行的活動不同微克的。 但不要告訴我這個不能簡化??!

 var t = (from ug in uof.Ugs.All().ToList() 
       from upcomingEvent in ug.Events 
       where upcomingEvent.Date >= DateTime.Today 
       select new 
       { 
        ug, 
        upcomingEvent 
       }).ToList(); 

     var s = (from ug in t.Select(x => x.ug).Distinct() 
       select new UG 
       { 
        Id = ug.Id, 
        Name = ug.Name, 
        Description = ug.Description, 
        WebSite = ug.WebSite, 
        Events = ug.Events.Where(x => x.Date >= DateTime.Today).ToList() 
       }).ToList(); 

UPDATE2

添加的圖像顯示,即使基本脈絡操縱我仍然得到2個事件,事件的時候我拿1!只要你想它

exampledebugimage

回答

2

你有沒有試過?:

var query = Xs 
.Select(x => new { x, yCol = x.YCol.Where(y => y.Date >= DateTime.Today) }) 
.AsEnumerable() 
.Select(x => x.x) 
.ToList(); 

參見:http://blogs.msdn.com/b/alexj/archive/2009/10/13/tip-37-how-to-do-a-conditional-include.aspx

所有這些.ToList使用將意味着你過濾之前,從數據庫加載整個表。所以要注意這一點。

UPDATE:作爲修正不工作的許多一對多

作爲Slauma在評論中提到要確保,如果你要提交變化您不使用這種技術更改跟蹤會認爲你改變了收藏。或者甚至更好的確保你使用.AsNoTracking(),無論如何它都會提高性能。

我們可以使用與上述相同的解決方案,但對於多對多略有不同。看到這個例子:

[TestClass] 
public class ContextTest 
{ 
    [TestMethod] 
    public void FixupTest() 
    { 
     Database.SetInitializer(new DropCreateDatabaseAlways<Context>()); 

     using (var db = new Context()) 
     { 
      db.Groups.Add(new Group 
      { 
       Name = "G1", 
       Users = new List<User>{ 
        new User{ Name = "M"}, 
        new User{Name = "S"} 
       } 
      }); 

      db.SaveChanges(); 
     } 

     using (var db = new Context()) 
     { 
      var group = db.Groups 
       .Select(g => new { g, Users = g.Users.Where(u => u.Name == "M") }) 
       .AsEnumerable() 
       .Select(g => { 
        g.g.Users = g.Users.ToList(); 
        return g.g; 
       }) 
       .First(); 

      Assert.AreEqual(1, group.Users.Count); 
     } 
    } 


} 



public class User 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 

    public ICollection<Group> Groups { get; set; } 
} 



public class Group 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 

    public ICollection<User> Users { get; set; } 
} 

測試通過而產生的SQL是:

SELECT 
[Project1].[ID] AS [ID], 
[Project1].[Name] AS [Name], 
[Project1].[C1] AS [C1], 
[Project1].[ID1] AS [ID1], 
[Project1].[Name1] AS [Name1] 
FROM (SELECT 
    [Extent1].[ID] AS [ID], 
    [Extent1].[Name] AS [Name], 
    [Join1].[ID] AS [ID1], 
    [Join1].[Name] AS [Name1], 
    CASE WHEN ([Join1].[Group_ID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1] 
    FROM [dbo].[Groups] AS [Extent1] 
    LEFT OUTER JOIN (SELECT [Extent2].[Group_ID] AS [Group_ID], [Extent3].[ID] AS [ID], [Extent3].[Name] AS [Name] 
     FROM [dbo].[GroupUsers] AS [Extent2] 
     INNER JOIN [dbo].[Users] AS [Extent3] ON [Extent3].[ID] = [Extent2].[User_ID]) AS [Join1] ON ([Extent1].[ID] = [Join1].[Group_ID]) AND (N'Mikael' = [Join1].[Name]) 
) AS [Project1] 
ORDER BY [Project1].[ID] ASC, [Project1].[C1] ASC 
+0

嘿邁克,因爲它是多對多的,沒有做ToList()並且等待查詢結束,會導致錯誤。這是因爲多對多的循環引用。但我會嘗試你的選擇,看看這是否仍然有效。 – Depechie 2012-03-18 20:29:19

+0

就像我想的那樣,錯誤:「已經有一個與此命令關聯的打開DataReader,它必須先關閉」仍然存在!這是y => y.Date ...部分,因爲Y也有一個Y.Xs集合! – Depechie 2012-03-18 20:32:30

+0

我認爲這是一個連接字符串問題:請看這裏http://social.msdn.microsoft.com/Forums/en-MY/adonetefx/thread/8cbe2049-53c9-4c02-b040-18ee30fd7800 – 2012-03-18 20:40:06

3

EF不支持這種情況下,是什麼,但是你可以做的是:

var date = DateTime.Date; 
var query = from x in Xs     
      select new 
      { 
       X = x 
       Ys = x.Ys.Where(i = > i.RegistrationDate > date) 
      } 

,這將給你X的集合與他們對應的Y的比賽你那標準。

+0

幾乎正確的......但現在我得到幾個X的兩倍!並且在查詢之後添加一個獨特的元素並沒有幫助...這是因爲many2many,所以只有當'found'X還沒有出現在結果列表中時纔會發生select new。有什麼想法嗎? – Depechie 2012-03-18 19:40:22

+0

@Depechie和ntziolis:我認爲你必須刪除從'中的Y x.Ys'線和替換''通過y' i'。 – Slauma 2012-03-18 21:56:21

+0

@Slauma Thx,簡單的複製和粘貼錯誤,它現在已經修復 – ntziolis 2012-03-19 15:24:31