0

私のモデル クラス OwnedModule には、Guid として OwnerID があります。

OwnedModule とその OwnerName からの同じ Guid 値を含む BusinessUnit と呼ばれる別のモデル クラスがあります。

ハードウェアに関するすべての詳細が含まれていますが、名前ではなく Guid 値として所有者が含まれている OwnedModule の詳細を表示したいため、ビュー モデルを作成しました。

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

Entity Framework がクエリを作成するとき、渡された式ツリーの検査に依存します。メソッド呼び出しに遭遇すると、それを同等の SQL メソッドにマップしようとします (正規メソッドについては、こちらを参照してください)。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 に答える