通用的Repository<TPoco> 是这里的通用方法。
即为每个 POCO 重复使用 1 个存储库。
它也常与工作单元模式一起使用,将更新组合成一个逻辑工作单元。
这是一个基本的演示来说明这一点。
但理想情况下,IRepository 在核心层中声明
和一个数据访问层实现 Repositiry:IRepository 以保持 ef 引用
在核心域层之外。 (这是另一个需要研究的重要相关代码架构问题)
这个演示太短了IRepository<t>
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace repofT
{
class Program
{
static void Main(string[] args)
{
// Kick Start Repository of T demo
// There are advance models combining context creation / unit of work and repository.
// The concept of Inversion of Control / Dependency injection should be inestigated
// for the people new to IOC
// SIMPLIFIED Unit of Work and Respository of T sample
var ctx = new MyContext();
var uow = new UnitOfWork(ctx);
var rep = new Repository<MyPoco>(ctx);
addTest(rep, uow);
var poco1 = FindTest(rep);
ChangeTest(poco1, rep, uow);
Console.ReadKey();
}
private static void ChangeTest(MyPoco poco1, Repository<MyPoco> rep, UnitOfWork uow)
{
poco1.Content = "Test - was changed";
rep.Change(poco1);
uow.Commit();
DumpTest(rep);
}
private static MyPoco FindTest(Repository<MyPoco> rep)
{
var poco1 = rep.Find(1);
Console.WriteLine(poco1.Id + " : " + poco1.Content);
return poco1;
}
private static void addTest(Repository<MyPoco> rep, UnitOfWork uow)
{
var mypoco = new MyPoco()
{
Content = "Test" + System.DateTime.Now.ToString(CultureInfo.InvariantCulture),
};
rep.Add(mypoco);
uow.Commit();
DumpTest(rep);
}
private static void DumpTest(Repository<MyPoco> rep)
{
var pocoList = rep.GetList(t => t.Content.StartsWith("Test"));
if (pocoList != null)
{
foreach (var poco in pocoList)
{
Console.WriteLine(poco.Id + " : " + poco.Content);
}
}
}
}
}
以及存储库/工作单元和上下文类
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Data.Entity.Validation;
using System.Linq.Expressions;
namespace repofT
{
/// <summary>
/// Note to the reader. NO error handling. You should add your preferred solution.
/// This is a stripped down sample to illustrate how Repository of T pattern works.
/// </summary>
public class MyContext : DbContext
{
public DbSet<MyPoco> MyPocos { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//fluent API....
base.OnModelCreating(modelBuilder);
var entity = modelBuilder.Entity<MyPoco>();
entity.HasKey(t => t.Id) ;
entity.Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
public class MyPoco
{
//virtuals for EF, especially Proxies and navigation, Use public get/set
public virtual int Id { get; set; }
public virtual string Content { get; set; }
}
public class Repository<TPoco> where TPoco : class, new()
{
public DbContext Context { get; private set; }
public Repository(DbContext context){
Context = context;
}
public IList<TPoco> GetList(Expression<Func<TPoco, bool>> predicate)
{
// Investigate returning IQueryable versus IList as you learn more.
return GetQuery(predicate).ToList();
}
public IQueryable<TPoco> GetQuery(Expression<Func<TPoco, bool>> predicate)
{
// Investigate returning IQueryable versus IList as you learn more.
return Context.Set<TPoco>().Where(predicate);
}
public TPoco Get(Expression<Func<TPoco, bool>> predicate)
{
return Context.Set<TPoco>().FirstOrDefault(predicate);
}
public TPoco Find(params object[] keyValues)
{
return Context.Set<TPoco>().Find(keyValues);
}
public TPoco Attach(TPoco poco)
{
return Context.Set<TPoco>().Add(poco);
}
public TPoco Add(TPoco poco){
return Context.Set<TPoco>().Add(poco);
}
public TPoco AddOrUpdate(TPoco poco){
return Context.Set<TPoco>().Add(poco);
}
public TPoco Remote(TPoco poco){
return Context.Set<TPoco>().Remove(poco);
}
public void Change(TPoco poco){
Context.ChangeTracker.DetectChanges();
}
public void SetEntityState(TPoco poco, EntityState state = EntityState.Modified){
Context.Entry(poco).State = state;
}
}
public class UnitOfWork
{
public DbContext Context { get; protected set; }
public UnitOfWork(DbContext context){
Context = context;
}
public IEnumerable<DbEntityValidationResult> GetDbValidationErrors() { return
Context.GetValidationErrors();
}
public int Commit()
{
try {
var recs = Context.SaveChanges();
return recs;
}
catch (DbEntityValidationException efException){
var errors = GetDbValidationErrors(); // DO SOMETHING HERE !!!!!
return -1;
}
}
}
}