LEFT JOIN в LINQ для объектов?

Я пытаюсь LINQ для сущностей.

У меня проблема со следующим: я хочу, чтобы это сделало следующее:

SELECT T_Benutzer.BE_User ,T_Benutzer_Benutzergruppen.BEBG_BE FROM T_Benutzer LEFT JOIN T_Benutzer_Benutzergruppen ON T_Benutzer_Benutzergruppen.BEBG_BE = T_Benutzer.BE_ID 

самое близкое, к чему я пришел, это:

  var lol = ( from u in Repo.T_Benutzer //where u.BE_ID == 1 from o in Repo.T_Benutzer_Benutzergruppen.DefaultIfEmpty() // on u.BE_ID equals o.BEBG_BE where (u.BE_ID == o.BEBG_BE || o.BEBG_BE == null) //join bg in Repo.T_Benutzergruppen.DefaultIfEmpty() // on o.BEBG_BG equals bg.ID //where bg.ID == 899 orderby u.BE_Name ascending //, bg.Name descending //select u select new { u.BE_User ,o.BEBG_BG //, bg.Name } ).ToList(); 

Но это порождает те же результаты, что и внутреннее соединение, а не левое соединение.
Более того, он создает этот совершенно сумасшедший SQL:

 SELECT [Extent1].[BE_ID] AS [BE_ID] ,[Extent1].[BE_User] AS [BE_User] ,[Join1].[BEBG_BG] AS [BEBG_BG] FROM [dbo].[T_Benutzer] AS [Extent1] CROSS JOIN ( SELECT [Extent2].[BEBG_BE] AS [BEBG_BE] ,[Extent2].[BEBG_BG] AS [BEBG_BG] FROM ( SELECT 1 AS X ) AS [SingleRowTable1] LEFT OUTER JOIN [dbo].[T_Benutzer_Benutzergruppen] AS [Extent2] ON 1 = 1 ) AS [Join1] WHERE [Extent1].[BE_ID] = [Join1].[BEBG_BE] OR [Join1].[BEBG_BE] IS NULL ORDER BY [Extent1].[BE_Name] ASC 

Как я могу сделать левое соединение в LINQ-2-сущностях таким образом, чтобы другой человек все еще мог понять, что делается в этом коде?

и наиболее предпочтительно, где сгенерированный SQL выглядит следующим образом:

 SELECT T_Benutzer.BE_User ,T_Benutzer_Benutzergruppen.BEBG_BE FROM T_Benutzer LEFT JOIN T_Benutzer_Benutzergruppen ON T_Benutzer_Benutzergruppen.BEBG_BE = T_Benutzer.BE_ID 

Ах, получил это сам.
Quirks и кварки LINQ-2-сущностей.
Это выглядит наиболее понятным:

 var query2 = ( from users in Repo.T_Benutzer from mappings in Repo.T_Benutzer_Benutzergruppen .Where(mapping => mapping.BEBG_BE == users.BE_ID).DefaultIfEmpty() from groups in Repo.T_Benutzergruppen .Where(gruppe => gruppe.ID == mappings.BEBG_BG).DefaultIfEmpty() //where users.BE_Name.Contains(keyword) // //|| mappings.BEBG_BE.Equals(666) //|| mappings.BEBG_BE == 666 //|| groups.Name.Contains(keyword) select new { UserId = users.BE_ID ,UserName = users.BE_User ,UserGroupId = mappings.BEBG_BG ,GroupName = groups.Name } ); var xy = (query2).ToList(); 

Удалите .DefaultIfEmpty() , и вы получите внутреннее соединение.
Это то, что я искал.

Вы можете прочитать статью, которую я написал для присоединений в LINQ здесь.

 var query = from u in Repo.T_Benutzer join bg in Repo.T_Benutzer_Benutzergruppen on u.BE_ID equals bg.BEBG_BE into temp from j in temp.DefaultIfEmpty() select new { BE_User = u.BE_User, BEBG_BG = (int?)j.BEBG_BG// == null ? -1 : j.BEBG_BG //, bg.Name } 

Ниже приведен эквивалент с использованием методов расширения:

 var query = Repo.T_Benutzer .GroupJoin ( Repo.T_Benutzer_Benutzergruppen, x=>x.BE_ID, x=>x.BEBG_BE, (o,i)=>new {o,i} ) .SelectMany ( x => xiDefaultIfEmpty(), (o,i) => new { BE_User = ooBE_User, BEBG_BG = (int?)i.BEBG_BG } ); 

Может быть, я приду позже, чтобы ответить, но прямо сейчас я сталкиваюсь с этим … если помогает, есть еще одно решение (как я его решил).

  var query2 = ( from users in Repo.T_Benutzer join mappings in Repo.T_Benutzer_Benutzergruppen on mappings.BEBG_BE equals users.BE_ID into tmpMapp join groups in Repo.T_Benutzergruppen on groups.ID equals mappings.BEBG_BG into tmpGroups from mappings in tmpMapp.DefaultIfEmpty() from groups in tmpGroups.DefaultIfEmpty() select new { UserId = users.BE_ID ,UserName = users.BE_User ,UserGroupId = mappings.BEBG_BG ,GroupName = groups.Name } ); 

Кстати, я пробовал использовать код Stefan Steiger, который также помогает, но он был медленнее, чем черт.

Вы можете использовать это не только в сущности, но и хранить процедуру или другой источник данных:

 var customer = (from cus in _billingCommonservice.BillingUnit.CustomerRepository.GetAll() join man in _billingCommonservice.BillingUnit.FunctionRepository.ManagersCustomerValue() on cus.CustomerID equals man.CustomerID // start left join into a from b in a.DefaultIfEmpty(new DJBL_uspGetAllManagerCustomer_Result() ) select new { cus.MobileNo1,b.ActiveStatus }); 

Легкий способ – использовать ключевое слово Let. Это работает для меня.

 from AItem in Db.A Let BItem = Db.B.Where(x => x.id == AItem.id ).FirstOrDefault() Where SomeCondition Select new YourViewModel { X1 = AItem.a, X2 = AItem.b, X3 = BItem.c } 

Это симуляция Left Join. Если каждый элемент таблицы B не соответствует элементу A, BItem возвращает значение null

  • LINQ to Entities не распознает метод 'System.String Format (System.String, System.Object, System.Object)'
  • Сколько Include я могу использовать в ObjectSet в EntityFramework для сохранения производительности?
  • «Дата» не поддерживается в LINQ to Entities. Поддерживаются только инициализаторы, сущности и свойства навигации сущности
  • Объект или сложный тип '' не могут быть сконструированы в запросе LINQ to Entities
  • Значение cast для значения «Int32» не выполнено, поскольку материализованное значение равно null
  • Как преобразовать DbSet в инфраструктуру Entity в ObjectQuery
  • Entity Framework 4 Single () vs First () vs FirstOrDefault ()
  • LINQ to Entities не распознает метод
  • Сравнение с регистром LINQ to Entities
  • Включить внуков в EF Query
  • Указанный член типа «Дата» не поддерживается в LINQ to Exities Exception
  • Давайте будем гением компьютера.