我有两张表,例如promotionalOffers和PromotionalOffersUsed
我现在使用连接获取匹配记录我想要包含不同的条件,例如 PromotionalOffers.ISVCSPId = 10和PromotionalOffersUsed.OfferId为空
我使用左连接工作预期在sql中编写了查询,但我无法在linq中编写相同的查询
这里是我的SQL查询
SELECT *
FROM PromotionalOffers
left JOIN PromotionalOffersUsed ON PromotionalOffers.Id = PromotionalOffersUsed.OfferId where PromotionalOffers.ISVCSPId =10 and PromotionalOffersUsed.OfferId is null
我的linq查询
(from s in db.PromotionalOffers
join e in db.PromotionalOffersUsed on s.Id equals e.OfferId
where s.ISVCSPId == iSVCSPData.Id
select s).ToListAsync();
我无法在此处加入左连接
答案 0 :(得分:1)
对于左连接,您必须这样做,以下是linq
中左外连接的示例var leftFinal =
from l in lefts
join r in rights on l equals r.Left into lrs
from lr in lrs.DefaultIfEmpty()
select new { LeftId = l.Id, RightId = ((l.Key==r.Key) ? r.Id : 0 };
查询
SELECT *
FROM PromotionalOffers
left JOIN PromotionalOffersUsed ON PromotionalOffers.Id = PromotionalOffersUsed.OfferId where PromotionalOffers.ISVCSPId =10 and PromotionalOffersUsed.OfferId is null
linq中的暂定查询
var leftFinal =
(from l in PromotionalOffers.Where(p=> p.ISVCSPId ==10)
join r in PromotionalOffersUsed on l.ID equals r.OfferId into lrs
from lr in lrs.DefaultIfEmpty()
select
new { LeftId = l.Id, RightId = ((l.ID==r.OfferId ) ? r.OfferId : -1 }
).where(d=> d.RightID != -1);
答案 1 :(得分:1)
试试这个;
(from s in db.PromotionalOffers
join e in db.PromotionalOffersUsed on s.Id equals e.OfferId into joinT
from e in joinT.DefaultIfEmpty()
where s.ISVCSPId == 10 && (e == null || e.OfferId == null)
select new { PromotionalOffers = s, PromotionalOffersUsed = joinT } ).ToListAsync();
答案 2 :(得分:0)
显然,PromotionalOffers
之间存在一对多关系
和PromotionalOffersUsed
:每个PromotionalOffer
都有零个或多个PromotionalOffersUsed
,而每个PromotionalOffersUsed
只属于一个PromotionalOffer
。
如果您遵循entity framework conventions to design this one-to-many关系,则不需要进行连接,也不需要左外连接,而是使用ICollection类:
class PromotionalOffer
{
public int Id {set; set;}
// a PromotionalOffer has zero or more PromotionalOfferUsed
public virtual ICollection<PromotionalOfferUsed> PromitionalOffersUsed {get; set;}
...
}
class PromotionalOfferUsed
{
public int Id {set; set;}
// every PromotionalOffersUsed belongs to exactly one PromotionalOffer
// using foreign key:
public int PromotionalOfferId {get; set;}
public PromotionalOffer PromotionalOffer {get; set;}
...
}
class MyDbContext: DbContext
{
public DbSet<PromotionalOffer> PromotionalOffers {get; set;}
public DbSet<PromotionalOfferUsed> PromotionalOffersUsed {get; set;
}
通常,这对于实体框架来说已经足够了解您设计了一对多关系。
我们需要一些流畅的API的唯一原因是因为奇怪的复数:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// PromotionalOffersUsed are stored in a table with name PromotionOffersUsed:
modelBuilder.Entity<PromotionalOfferUsed>().ToTable("PromotionalOffersUdsed");
// Every PromotionalOffer has zero or more PromotionalOfferUsed
// every PromotionalOfferUsed belongs to exactly one (required) PromotionalOffer
// using foreign key PromtionalOfferId
modelBuilder.Entity<PromotionalOffer>
.HasMany(promotionalOffer => promotionalOffer.PromotionalOffersUsed)
.WithRequired(promotionalOfferUsed => promotionOfferUsed.PromotionalOffer)
.HasForeignKey(post => post.BlogId);
base.OnModelCreating(modelBuilder);
}
再一次,如果您有标准单数和复数(人/人;帐户/帐户,订单/订单),则不需要这种流畅的API。
现在您的查询:在集合中思考,而不是在联接中。
将所有ISVCSPId等于10的PromotionalOffers一起给我 使用OfferId等于null的所有PromotionalOffersUsed
using (var dbContext = new MyDbContext())
{
var result = dbContext.PromotionalOffers
.Where(promotionalOffer => promotionalOffer.ISVCSPID == 10)
.Select(promotionalOffer => new
{ // select only the properties you will be using:
ISVCSPID = promotionalOffers.ISVSPID,
... // other properties from promotionalOffers
PromotionalOffersUsed = promotionalOffers.PromtionalOffersUsed
.Where(promotionalOffersUsed => promotionalOffersUsed.OfferId == null)
.Select(promotionalOffersUsed => new
{
// again: select only the properties of PromotionalOffersUsed
// that you will be using
Id = promotionalOffersUsed.Id,
... // other properties
})
.ToList();
}
}
因为实体框架知道有一对多的外键,所以它会为你做正确的左外连接。