1

Entity Framework 5 を使用して、コンテキストからエンティティを取得し、オプションのパラメーターを使用してフィルター処理し、関連するエンティティを含め、結果の順序を設定するジェネリック メソッドを作成しました。ただし、メソッドに include プロパティのセットを渡すと、結合を使用してクエリが変更され、関連するエンティティが含まれることはありません。クエリが更新されない理由はありますか?

方法:

public virtual IQueryable<TEntity> Get(
    Expression<Func<TEntity, bool>> filter = null,
    string includeProperties = "",
    Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null)
{        
    IQueryable<TEntity> query = dbSet.AsExpandable();

    if (filter != null)
    {
        query = query.Where(filter);
    }

    foreach (var includeProperty in includeProperties.Split
        (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
    {
        query = query.Include(includeProperty);
    }

    if (orderBy != null)
    {
        return orderBy(query);
    }
    else
    {
        return query;
    }
}

それ以前のクエリforeach (var includeProperty...はその後変更されません

{SELECT 
[Extent1].[Pid] AS [Pid],     
[Extent1].[Created] AS [Created], 
[Extent1].[Creator] AS [Creator]
FROM [Administrator] AS [Extent1]}

編集...詳細情報

もともと私は次のメソッド呼び出しを使用していAdministratorDTO admin = unitOfWork.AdministratorComponent.GetByID(userPid);ました: 次の POCO クラスで:

public virtual TEntity GetByID(object id)
{
    return dbSet.Find(id);
}

public class Administrator : IPrincipal
{
    [Key]
    [Required]
    [StringLength(1024)]
    [Display(Name = "PID")]
    public string Pid { get; set; }

    public DateTime Created { get; set; }

    public string Creator { get; set; }

    ...

    public ICollection<Role> Roles { get; set; }

    public ICollection<Area> Areas { get; set; }

    ...
}

AutoMapper を使用して、次の構成で DTO にマップします。

public class AdministratorDTO
{
    [Key]
    [Required]
    [StringLength(1024)]
    [Display(Name = "PID")]
    public string Pid { get; set; }

    ...

    public string[] Roles { get; set; }

    public string[] Areas { get; set; }
}


public class WebApiApplication : System.Web.HttpApplication
{
...
AutoMapperConfiguration.Configure();
}

public static class AutoMapperConfiguration
{
    public static void Configure()
    {
        ConfigureAdministratorMapping();
        ...
    }

    private static void ConfigureAdministratorMapping()
    {
        Mapper.CreateMap<Administrator, AdministratorDTO>()
            .ForMember(dest => dest.Roles, 
                opt => opt.MapFrom(src => src.Roles == null ? 
                    null : src.Roles.Select(r => r.Name).ToArray())) 
            .ForMember(dest => dest.Areas, 
                opt => opt.MapFrom(src => src.Areas == null ?
                    null : src.Areas.Select(a => a.Id).ToArray()));

        ...
    }
}

public class BusinessComponent<TEntity, TDto> 
    : IBusinessComponent<TEntity, TDto>
        where TEntity : class
        where TDto : class
{
    ...
    protected TDto Flatten(TEntity entity)
    {
        return Mapper.Map<TEntity, TDto>(entity);
    }
}

Administrator私の理解では、のナビゲーション プロパティ (領域と役割) を積極的virtualに読み込まれるようにマークしなかった場合、DTO で空の文字列 [] を取得し続けました。

メソッドに入る TEntity パラメーターを調べたところ、を呼び出すFlattenにAreas/Roles があったため、AutoMapper とは関係がないと思います。null Map

次に、次のメソッド呼び出しを使用してみました。

AdministratorDTO admin = unitOfWork.AdministratorComponent
    .Get(filter: a => a.Pid == "csherman", includeProperties: "Roles, Areas")
    .SingleOrDefault();

最後に、Includeナビゲーション プロパティが ではなかったために が無視された場合に備えて、クラスのとの両方にキーワードvirtualを追加しました。これを行うと、メソッドとメソッドの両方が機能し、TEntityパラメータに Areas/Roles が含まれ、DTO に文字列配列が設定されました。virtualAreasRolesAdministratorGetByIDGet(filter: ..., includeProperties: ...)Flatten

問題は解決したと思いますが...

質問は、特にGetByIdメソッドの場合、virtualキーワードを使用しても機能しないのはなぜですか?

EF が元のメソッド呼び出しの時点からの予測を実際に考慮している場合、これらのエンティティが含まれるのはなぜでしょうか?

4

2 に答える 2

2

インクルードの後に​​何らかのプロジェクションを行うと、インクルードは機能しません。

これを扱う投稿とその回避方法を次に示します。

そして、これもそれを扱うSOの質問です。

virtual編集:あなたの編集に応えて、キーワードがあなたのInclude仕事をするが、それなしでは機能しない理由を見つけることができるかどうかを調べてみました. それに直接答えられるようなものは何も見つかりませんでした。

ナビゲーション プロパティのvirtualキーワードは、このプロパティが遅延読み込みを使用する必要があることを Entity Framework に伝えます。せっせとロードしたい時があるとすれば、使う時ですIncludeIncludeそのために作られていると思います。その名前のプロパティを具体的に探そうとしvirtual、見つからない場合は例外なく優雅に死ぬと思います。の実装が完全virtualに見逃されていると思うので、それをマークしないと。Includeこの推測は、私が見た記事のどれもがInclude遅延読み込みのコンテキスト以外で言及していないという事実に基づいています。これは、virtualキーワードの使用を意味します。

于 2013-02-28T16:53:27.597 に答える