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 に文字列配列が設定されました。virtual
Areas
Roles
Administrator
GetByID
Get(filter: ..., includeProperties: ...)
Flatten
問題は解決したと思いますが...
質問は、特にGetById
メソッドの場合、virtual
キーワードを使用しても機能しないのはなぜですか?
EF が元のメソッド呼び出しの時点からの予測を実際に考慮している場合、これらのエンティティが含まれるのはなぜでしょうか?