[英]How to get a complement list of objects using linq and EntityFramework
I have two types, one is a cut down of the other: 我有两种类型,一种是另一种类型:
public class A
{
public int ID { get; set; }
public string Name { get; set; }
}
public class B
{
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
I have a List<A>
called As
that was passed to me by a client and I have an EntityFramework DbContext with a DbSet<B>
called Bs
. 我有一个名为
As
的List<A>
由客户端传递给我,我有一个EntityFramework DbContext,其中DbSet<B>
被称为Bs
。 The two types can be matched on ID. 这两种类型可以在ID上匹配。
What I want to get is all the As
that are not in Bs
. 我想要的是所有不在
Bs
的As
。 How would you write that in Linq? 你会怎么在Linq写的? I'm trying to use a join but I can't seem to get my head around it.
我正在尝试使用连接,但我似乎无法理解它。
In T-SQL I would do something like this: 在T-SQL中我会做这样的事情:
SELECT A.*
FROM A LEFT JOIN B
ON A.ID = B.ID
WHERE B.ID is NULL
You can do it like this: 你可以这样做:
List<A> As = ... //This is a list in memory
//Get all ids of As
var A_ids = As.Select(x => x.ID).ToList();
//Get all ids that are in both As (memory) and TableB (database)
//We put them in a HashSet for performance reasons
var ids_in_tableB_also =
new HashSet<int>(
db.TableB
.Where(x => A_ids.Contains(x.ID))
.Select(x => x.ID));
//Get the A objects that are in `As` but of which IDs are not in ids_in_tableB_also
//This operation would have been slower if we haven't used the HashSet above
var rest_of_As = As.Where(x => !ids_in_tableB_also.Contains(x.ID)).ToList();
Well, you can do in LINQ exactly the same as in SQL: 那么,您可以在LINQ中完全与SQL中相同:
var query =
from a in db.TableA
join b in db.TableB on a.ID equals b.ID into aBs
from b in aBs.DefaultIfEmpty()
where b == null
select a;
This is a standard antijoin pattern implemented with LINQ left outer join . 这是使用LINQ 左外连接实现的标准反连接模式。
EDIT: The above applies if both A and B are database tables. 编辑:如果A和B都是数据库表,则以上适用。 If the A is a memory list and B is a database table, then @Yacoub Massad answer is the way to go.
如果A是一个内存列表而B是一个数据库表,那么@Yacoub Massad的答案是可行的方法。
It might be a bit simplistic but have you considered the .Except method? 它可能有点简单,但你考虑过.Except方法吗?
https://msdn.microsoft.com/en-us/library/bb300779(v=vs.100).aspx https://msdn.microsoft.com/en-us/library/bb300779(v=vs.100).aspx
List<A> as = ...
List<B> bs = ...
var idsYouWant = as.Select(a => a.Id).Except(bs.Select(b=>b.Id)).ToList();
var wholeObjectsYouWant = as.Where(a => idsYouWant.Contains(a.Id));
Try this code 试试这个代码
dbContext.Set<A>()
.Join(
dbContext.Set<B>(),
a => a.ID,
b => b.ID,
(a, b) => new
{
aID = a.ID,
bID = b.ID,
aName = a.Name,
bName = b.Name,
bDescription = b.Description
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.