Сначала код Entity Framework - фильтрация много ко многим - PullRequest
0 голосов
/ 18 марта 2012

Маленький вопрос EF.У меня есть отношения многие ко многим в EF.X..Y Итак, когда у меня есть один X, есть свойство X.Ys.

Теперь я хочу использовать Linq Query для получения нескольких X, но я не хочу, чтобы все Y были внутри.выбранные X's.Я хочу, чтобы Y был отфильтрован по Y.RegistrationDate> Date.Today.

Поэтому, когда у меня будет один X и он будет проходить через .Y, я получу только будущие Y.

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();

ОБНОВЛЕНИЕ2

Добавлено изображение, чтобы показать, что даже с основнымиманипулирование контекстом Я все еще получаю 2 события, событие, когда я беру 1!

exampledebugimage

Ответы [ 2 ]

3 голосов
/ 18 марта 2012

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, которые соответствуют вашим критериям.

2 голосов
/ 19 марта 2012

Вы пробовали?:

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, которые вы используете, будут означать, что перед фильтрацией вы загрузите всю таблицу из БД.Так что следите за этим.

ОБНОВЛЕНИЕ: Поскольку исправление не работает со многими ко многим

Как Слаума упомянул в комментарияхубедитесь, что вы не используете эту технику, если вы собираетесь отправить изменения, так как отслеживание изменений будет думать, что вы изменили коллекцию.Или, еще лучше, убедитесь, что вы используете .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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...