在我的模型类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的名称。
但似乎我将所有者的名称设置为我的viewmodel视图的方式是错误的,当我运行应用程序时,我收到以下错误。
LINQ to Entities无法识别方法'System.String GetModuleOwner(System.Guid)'方法,并且此方法无法转换为商店表达式。
当我评论我设置了所有者值的行(所有者= GetModuleOwner(module.ModuleOwnerId))时,一切正常。
答案 0 :(得分:3)
当Entity Framework构建您的查询时,它依赖于对传递的表达式树的检查。遇到方法调用时,它会尝试使用(see this for the canonical methods)将其映射到等效的SQL方法。由于实体框架不了解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>
的{{1}}部分,否则会出现同样的问题。
答案 1 :(得分: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();
注意:我没有对此进行测试,因此可能会出现一些轻微的语法错误。
答案 2 :(得分: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;