Левый присоединиться в 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-entities таким образом, где другой человек все еще может понять, что делается в этом код ?
и наиболее предпочтительно там, где сгенерированный 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
5 ответов:
Ах, я сам это понял.
Причуды и кварки 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()
, и вы получаете внутреннее соединение.
Это было то, что я искал.
вы можете прочитать статью, которую я написал для joins в 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 => x.i.DefaultIfEmpty(), (o,i) => new { BE_User = o.o.BE_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 } );
кстати, я попытался использовать код Стефана Штайгера, который также помогает, Но он был медленнее, как ад.
вы можете использовать это не только в сущностях, но и в процедуре хранения или другом источнике данных:
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 }
это имитация левого соединения. Если каждый элемент в таблице B не соответствует элементу, BItem возвращает null