0

在我的模型类 OwnedModule 中,我将 OwnerID 作为 Guid。

还有另一个名为 BusinessUnit 的模型类,它包含来自 OwnedModule 及其 OwnerName 的相同 Guid 值。

我想展示 OwnedModule 的详细信息,其中包含有关硬件的所有详细信息,但所有者作为 Guid 值而不是名称,为此我创建了一个视图模型

public class OwnedModuleViewModel
    {
        public long Id { get; set; }
        public string ModuleId { get; set; }
        public string TypeName { get; set; }
        public string KindName { get; set; }
        public string Owner { get; set; }
        public DateTime OwnershipStart { get; set; }
    }
    public class IndexOwnedModule
    {
        public List<OwnedModuleViewModel> OwnedModules { get; set; }
    }

为了在我的存储库中显示所有这些细节,我有以下功能

    public IndexOwnedModule GetAllOwnedModules()
    {

        var modulesList = new IndexOwnedModule();

        var modules = (_dbSis.OwnedModules.OrderBy(module => module.Id).Select(module => new OwnedModuleViewModel
        {
            Id = module.Id,
            ModuleId = module.ModuleId,
            TypeName = module.ModuleType.TypeName,
            Owner = GetModuleOwner(module.ModuleOwnerId),//error here
            OwnershipStart = module.Start
        }));

        modulesList.OwnedModules = modules.ToList();
        return modulesList;

    }

    public string GetModuleOwner(Guid id)
    {
        var ownedModule =_dbSis.Set<BusinessUnit>().FirstOrDefault(t => t.Id == id);
        if (ownedModule != null) return ownedModule.Name;
        return null;
    }

在视图中将 guid 值显示为所有者并不方便,因此我想获取我拥有 GetModuleOwnerName 的名称。

但似乎我将所有者的名称设置为我的视图模型视图的方式是错误的,当我运行应用程序时,我收到以下错误。

LINQ to Entities 无法识别方法“System.String GetModuleOwner(System.Guid)”方法,并且该方法无法转换为存储表达式。

当我评论我设置所有者值的行时(Owner = GetModuleOwner(module.ModuleOwnerId)),一切正常。

4

3 回答 3

3

当实体框架构建您的查询时,它依赖于对传递的表达式树的检查。当它遇到一个方法调用时,它会尝试将它映射到一个等效的 SQL 方法使用(见this for the canonical methods)。由于 Entity Framework 不知道OwnedModuleViewModel.GetModuleOwner,它无法生成适当的 SQL 查询。在这种情况下,简单的方法是将您的方法的功能嵌入到查询中,而不是调用方法:

_dbSis.OwnedModules
      .OrderBy(module => module.Id)
      .Select(module => new OwnedModuleViewModel 
          {
              Id = module.Id,
              ModuleId = module.ModuleId,
              TypeName = module.ModuleType.TypeName,
              Owner = _dbSis.Set<BusinessUnit>()
                            .Where(t => t.Id == module.ModuleOwnerId)
                            .Select(t => t.Name).FirstOrDefault(),
              OwnershipStart = module.Start
          });

当然,这是假设_dbSis.Set<BusinessUnit>()DbSet<T>相同的一部分DbContext,否则会出现相同的问题。

于 2013-07-26T14:09:57.800 回答
1

在 Linq-To-Entities 中,针对上下文的 Linq 语句被转换为 SQL 语句。GetModuleOwner()将方法转换为 SQL显然是不可能的。您需要先获取 ModuleOwnerId,然后在另一个步骤中,对每个 ModuleOwnerId 调用 GetModuleOwner()。

或者您可以重组您的查询以使用连接:

var modules = from m in _dbSis.OwnedModules
              join b in _dbSis.BusinessUnit on m.ModuleOwnerId equals b.Id
              order by m.Id
              select new OwnedModuleViewModel {
                                      Id = m.Id,
                                      ModuleId = m.ModuleId,
                                      TypeName = m.ModuleType.TypeName,
                                      Owner = b.Name,
                                      OwnershipStart = m.Start};

modulesList.OwnedModules = modules.ToList();

注意:我没有对此进行测试,因此它可能有一些小的语法错误。

于 2013-07-26T14:10:37.100 回答
0

这可能是另一种选择

var ownedModules = _dbSis.OwnedModules.OrderBy(module => module.Id).Select(module => new
            {
                Id = module.Id,
                ModuleId = module.ModuleId,
                TypeName = module.ModuleType.TypeName,
                ModuleOwnerId = module.ModuleOwnerId,
                OwnershipStart = module.Start
            }).ToList().Select(m => new OwnedModuleViewModel
            {
                Id = m.Id,
                ModuleId = m.ModuleId,
                TypeName = m.TypeName,
                Owner = GetModuleOwner(m.ModuleOwnerId),
                OwnershipStart = m.OwnershipStart
            });
            ownedModulesList.OwnedModules = ownedModules.ToList();
            return ownedModulesList;
于 2013-07-28T14:43:11.130 回答