在c#EF6

时间:2019-06-23 09:08:27

标签: c# entity-framework mapping

我有一个Web服务,允许用户从数据库查询给定数据子集。我只会知道用户在运行时需要哪些字段。构建动态linq查询以仅从数据库中检索对象表本身中的字段的对应属性非常容易,但是如何动态指定要在相关表中检索的字段呢?听起来令人困惑,让我用示例进行解释。

因此,假设我的结构如下:

class User {
 public string Name {get; set;}
 public List<Role> Roles {get; set;}
}

class Role {
  public string RoleName {get; set;}
  public string RoleDescription {get; set;}
}

因此,用户和角色是EF6在我的代码优先数据库表生成中使用的对象。

现在,我有一个Web服务,希望从数据库中获取用户名和角色名称。它将发送类似

的参数
var requestData = "{fields: {'Name', 'Roles.RoleName'}}"`;

我只想从Roles集合中检索RoleName字段,因为知道另一个客户端可能只询问Roles.RoleDescription,所以我需要动态创建查询。理想情况下,我应该能够在IQueryable对象的Select级别上生成此文件,以避免从数据库中获取大量数据,而仅使用一个字段。

到目前为止,我已经尝试过:

使用System.Linq.Dynamic来检索User表的属性。像这样:

var dynamicFields = GetFieldsFromRequestData(requestData); // results in "Name, Roles" 
var query = context.Set<User>().Select(dynamicFields);
query.Load();

像魅力一样工作。但将查询“角色”集合中的所有字段。我似乎无法仅使用相同的策略从Roles表中选择Roles.RoleName列。

var query = context.Set<User>().Select("Name, Roles.RoleName");

不起作用。

我还尝试使用Linq.Expressions,它需要指定对象类型:

class UserDTO {
 public string Name {get; set;}
 public List<RoleDTO> Roles {get; set;}
}

class RoleDTO {
 public string RoleName {get; set;}
}

然后使用我生成的Linq.Expressions

var generatedExpression = GetFieldsFromRequestDataLinq(requestData); //
results in an expression = (user => New UserDTO {Name = user.Name, Roles = user.Roles });
var query = context.Set<User>().Select(generatedExpression);

像魅力EF一样工作,EF将Roles集合中的对象转换为RoleDTO对象。

但是,这意味着自从我定义RoleDTO类型以来,要预先知道要在Roles集合中查询哪些字段。这不是我想要的,因为我不知道查询的字段的列表。

因此,如果有人能很好地解决此问题,那就太好了。我愿意接受AutoMapper解决方案,Newtonsoft JSON方法,...

自10天以来一直在与之作战;-)

2 个答案:

答案 0 :(得分:0)

您应该能够在运行时将属性添加到匿名类型:

Add property to anonymous type after creation

利用反射查询看起来像:

    var query = context.Set<User>().Select(p=>{ 
        var dto = new UserDTO{};

        parameterNames.foreach(pn =>{
            var value = p.GetField( pn ).GetValue (p, null);
            UserDTO.Add(parameter, value);
        });
        return dto;
    });

答案 1 :(得分:0)

根据您提供的上下文,我建议尝试 OData / GraphQL

它通常足够灵活,能够处理这种情况,但会引起其他麻烦。