まあ、あなたはすでに正しい方向に進んでいます。あなたが望むことを実装するだけです:)
1.findメソッドに式を渡しているので、Where句でその式を使用するだけです
2.DbContextから正しいDbSetを取得してクエリを実行する必要があるだけです。DbContextには、特定のタイプのDbContextを取得するメソッドがあり、それを使用すると、次のようにクエリできます
public IQueryable<T> Find<T>(Expression<Func<T, bool>> query) where T : IMyDomainEntity
{
var dbSet = context.Set<T>();
return dbSet.Where(query);
}
3.ドメインオブジェクトがEFによってデータベースにマップされたものではない場合、DbContextクラスのDBにあるものに対してマッピングをカスタマイズする必要があります(そのためのオートマッパーは必要ありません)ので、このようなものがありますあなたの DbContext クラスで
public class MyContext : DbContext
{
...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.Map(a => a.ToTable("DB_USERS"))
.Property(a => a.Email).HasColumnName("MAIL");
base.OnModelCreating(modelBuilder);
}
}
DB のテーブル DB_USERS からクラス User にマップするには、フィールドなどに異なる名前を付けます。これに関する記事は次のとおりです。
http://www.codeproject.com/Articles/165720/Using-the-Code-First-Model-Configuration-Classes
DbContext クラスを変更したくない/変更できない場合は、属性を使用してプロパティを正しいテーブル列にマップすることもできます
http://msdn.microsoft.com/en-us/data/gg193958
または、DB にマップされたエンティティの別のセットを持ち、automapper を使用してそれらをドメイン オブジェクトに変換することもできますが、失うものはありません。クエリを具体化してドメイン モデルに自動マップする必要があるため、4 つのベロスが必要です。
4.特別なことをする必要はありません。EFが面倒を見てくれます
更新: DbContext にアクセスできないソリューション (完全に汎用的なバージョンではありませんが、機能します)
アイデアは、各ドメイン クラスのリポジトリのマッピング部分を作成して、すべてが正しくバインドされるようにすることです。User
ドメイン モデルとDBUser
テーブル モデルを続けます。
public class User : IDomainModelEntity
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
public class DBUser
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int USER_ID { get; set; }
[Required]
[MaxLength(150)]
public string USER_NAME { get; set; }
[Required]
[MaxLength(260)]
public string USER_MAIL { get; set; }
}
次に、マッピングされた基本的な GetAll クエリを実装するドメイン クラスごとに、抽象的なリポジトリと具体的なリポジトリを作成します。
public abstract class Repository<T> where T : IDomainModelEntity
{
protected readonly DbContext _context;
public Repository(DbContext context)
{
_context = context;
}
public abstract IQueryable<T> GetAll();
public IQueryable<T> Find(Expression<Func<T, bool>> predicate)
{
return GetAll().Where(predicate);
}
}
public class UserRepository : Repository<User>
{
public UserRepository(DbContext context)
: base(context)
{
}
public override IQueryable<User> GetAll()
{
return _context.Set<DBUser>()
.Select(u => new User
{
Id = u.USER_ID,
Name = u.USER_NAME,
Email = u.USER_MAIL
});
}
}
今それを使用するには、リポジトリでfindまたはget allを呼び出すだけです...
using (var context = new CompanyDbContext())
{
var repo = new UserRepository(context);
var list = repo.Find(a=>a.Id >= 2).ToList();
list.ForEach(a => Console.WriteLine("Id: {0}, Name {1}, email {2}", a.Id, a.Name, a.Email));
}
使用する必要がある各ドメイン クラスのリポジトリを渡す必要があるため、完全に汎用的ではありませんが、許容できる妥協点である可能性があります。
お役に立てれば