简体   繁体   English

如何使用linq和EntityFramework获取对象的补充列表

[英]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 . 我有一个名为AsList<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 . 我想要的是所有不在BsAs 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM