简体   繁体   English

EF Core 连接结果的通用类型 class

[英]Generic type class for EF Core join results

Trying to come up with a dynamically typed class for storing results from querying my EF Core dbcontext.试图提出一个动态类型的 class 来存储查询我的 EF Core dbcontext 的结果。 What I'm trying to avoid is creating a new class for every join combination I might need.我要避免的是为我可能需要的每个连接组合创建一个新的 class 。 For example, I have these 2 entities that I want to join in a query:例如,我有这 2 个要加入查询的实体:

List<Person> People = new List<Person>(){ new Person(){ Id = 1, Name = "John Doe"}};
List<Address> Addresses = new List<Address>(){ new Address(){ Id = 1, City = "Anonland"}};

What I have tried is:我尝试过的是:

a) Creating a generic type class that just contains one each of the provided type params a) 创建一个泛型类型 class ,它只包含一个提供的类型参数

public class QueryResult<T1, T2> {
        public T1 t1;
        public T2 t2;

        public QueryResult(T1 t1, T2 t2) {
            this.t1 = t1;
            this.t2 = t2;
        }
    }

then然后

List<QueryResult<Person, Address> res = 
            People.Join(
                Addresses,
                p => p.Id,
                a => a.Id,
                (p,a) => new QueryResult<Person, Address>(p, a))
            .ToList();

foreach (var x in res){
    Console.WriteLine($"{x.t1.Name} - {x.t2.City}");
}

I can live with this, but I would prefer to have more descriptive var names than t1 / t2, which I don't think I can accomplish using this method.我可以忍受这一点,但我更愿意使用比 t1 / t2 更具描述性的 var 名称,我认为我无法使用这种方法来完成。

and b) using an implementation of Dictionary<string,object> : b) 使用Dictionary<string,object>的实现:

public class QueryResult<T1, T2> : Dictionary<string, object> {
    public QueryResult(T1 a, T2 b){
        this.Add(typeof(T1).ToString(), a);
        this.Add(typeof(T2).ToString(), b);        
    }
}

then然后

List<QueryResult<Person, Address> res = 
            People.Join(
                Addresses,
                p => p.Id,
                a => a.Id,
                (p,a) => new QueryResult<Person, Address>(p, a))
            .ToList();

foreach (var x in res){
            Console.WriteLine(((Person)x["Person"]).Name + " - " + ((Address)x["Address"]).City);
        }

This also works and is more descriptive, but then accessing and casting the objects is long-winded and redundant.这也有效并且更具描述性,但是访问和转换对象是冗长且多余的。

Is there some sort of middle ground here that I'm missing?这里有什么我想念的中间立场吗? Or maybe just going about this entirely the wrong way?或者也许只是以完全错误的方式去做这件事?

Why not just use value tuples available since C# 7 which allow to specify field names ?为什么不只使用自 C# 7 起允许指定字段名称值元组

List<(Person Person, Address Address)> res = 
            People.Join(
                Addresses,
                p => p.Id,
                a => a.Id,
                (p,a) => (p, a))
            .ToList();

Or using var :或使用var

var res = People.Join(
                Addresses,
                p => p.Id,
                a => a.Id,
                (p,a) => (Person: p, Address: a))
            .ToList();
 
foreach (var x in res){
        Console.WriteLine(x.Person.Name + " - " + x.Address.City);
    }

So for future reference, 'tuple literals' are not supported in expression trees, so I was getting compiler errors with this.因此,为了将来参考,表达式树不支持“元组文字”,所以我得到了编译器错误。 What I ended up having to do is instantiate a tuple explicitly我最终要做的是显式实例化一个元组

List<Tuple<Person, Address>> res = 
            People.Join(
                Addresses,
                p => p.Id,
                a => a.Id,
                (p,a) => new Tuple<Person, Address>(p, a))
            .ToList();

foreach (var x in res){
    // x.Item1.Name, etc
}

which still introduces the less descriptive Item1...ItemN, but at least avoids creating a custom class.它仍然引入了描述性较差的 Item1...ItemN,但至少避免了创建自定义 class。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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