我正在尝试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
答案 0 :(得分:113)
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()
,即可获得内部联接
这就是我一直在寻找的。 p>
答案 1 :(得分:38)
您可以阅读我为LINQ here
中的联接撰写的文章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
}
);
答案 2 :(得分:5)
可能是我后来回答但是现在我正面对这个...如果有帮助还有一个解决方案(我解决它的方式)。
import squants.space.{Radians, Meters}
import squants.{Angle, Length}
object Geospatial {
case class Longitude(angle: Angle) {
require(
(Radians(-Math.PI) <= angle) && (angle < Radians(Math.PI)),
"angle.inRadians must be greater than or equal to -Math.PI and less than Math.PI"
)
}
case class Latitude(angle: Angle) {
require(
(Radians(-(Math.PI * 0.5d)) <= angle) && (angle < Radians(Math.PI * 0.5d)),
"angle.inRadians must be greater than or equal to -(Math.PI * 0.5d) and less than (Math.PI * 0.5d)"
)
}
case class Distance(length: Length) {
require(
Meters(0.0d) <= length,
"length.inMeters must be greater than or equal to 0.0d"
)
}
case class Bearing(angle: Angle) {
require(
(Radians(0.0d) <= angle) && (angle < Radians(Math.PI * 2.0d)),
"angle.inRadians must be greater than or equal to 0.0d and less than (Math.PI * 2.0d)"
)
}
case class Coordinate(longitude: Longitude, latitude: Latitude)
def calculateDistance(
coordinate1: Coordinate,
coordinate2: Coordinate
): (Distance, Bearing, Bearing) = {
def calculateDistanceUsingLegacyCodeRifeWithDoubles(
coordinate1LongitudeInRadians: Double,
coordinate1LatitudeInRadians: Double,
coordinate2LongitudeInRadians: Double,
coordinate2LatitudeInRadians: Double
): (Double, Double, Double) = {
//Legacy code encapsulated here only works with meters and radians
//returns (distance, initial bearing, final bearing)
(1.0d, 1.0d, 2.0d) //TODO: replace with real calculation results
}
val (coordinate1InRadians, coordinate2InRadians) = (
(coordinate1.longitude.angle.toRadians, coordinate1.latitude.angle.toRadians),
(coordinate2.longitude.angle.toRadians, coordinate2.latitude.angle.toRadians)
)
val (distanceInMeters, bearingInitialInRadians, bearingFinalInRadians) =
calculateDistanceUsingLegacyCodeRifeWithDoubles(
coordinate1InRadians._1,
coordinate1InRadians._2,
coordinate2InRadians._1,
coordinate2InRadians._2
)
(
Distance(Meters(distanceInMeters)),
Bearing(Radians(bearingInitialInRadians)),
Bearing(Radians(bearingFinalInRadians))
)
}
def calculateCoordinate(
coordinate1: Coordinate,
bearingInitial: Bearing,
distance: Distance
): Coordinate = {
def calculateCoordinateUsingLegacyCodeRifeWithDoubles(
coordinate1Longitude: Double,
coordinate1Latitude: Double,
bearingInitialInRadians: Double,
distanceInMeters: Double
): (Double, Double) = {
//Legacy code encapsulated here only works with meters and radians
//returns (longitude, latitude)
(-1.0d, 1.0d) //TODO: replace with real calculation results
}
val (coordinate1InRadians, bearingInitialInRadians, distanceInMeters) = (
(coordinate1.longitude.angle.toRadians, coordinate1.latitude.angle.toRadians),
bearingInitial.angle.toRadians,
distance.length.toMeters
)
val (longitude, latitude) =
calculateCoordinateUsingLegacyCodeRifeWithDoubles(
coordinate1InRadians._1,
coordinate1InRadians._2,
bearingInitialInRadians,
distanceInMeters
)
Coordinate(Longitude(Radians(longitude)), Latitude(Radians(latitude)))
}
}
顺便说一句,我尝试使用Stefan Steiger代码也很有帮助,但是速度慢了。
答案 3 :(得分:3)
简单的方法是使用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表中的每个项目都与A项目不匹配,则BItem返回null
答案 4 :(得分:1)
您不仅可以在实体中使用它,还可以在存储过程或其他数据源中使用它:
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 });