实体框架代码首先 - 多对多过滤

时间:2012-03-18 14:42:05

标签: entity-framework many-to-many

小EF问题。 我在EF中映射了多对多的关系。 X..Y 因此,当我有一个X时,有一个属性X.Ys。

现在我想要做的是使用Linq查询来获取几个X,但我不想让所有Y都在选定的X中。 我希望在Y.RegistrationDate>上过滤Y. Date.Today。

所以,当我有一个X并且通过itY。时,我只会得到未来的Y.

更新 这是有效的,导致S具有不同的ug,其关系仅包含即将发生的事件。 但不要告诉我这不能简化?? !!

        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 个答案:

答案 0 :(得分:3)

EF不支持您想要的场景,但您可以这样做:

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

这将为您提供符合您标准的相应Y的X集合。

答案 1 :(得分: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意味着你在过滤之前从db加载整个表。所以要小心。

更新:由于修正无法使用多对多

正如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