实体框架是否有一些自动化的功能,这意味着我不必重新编写crud控制器和视图来使用我的存储库和统一框架注入:(?
它在控制器中显式引用entityframework数据库上下文...然后在控制器本身内进行实际数据操作......
例如,这最终出现在我的控制器中: [HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include="ProductID,Title")] Product product)
{
if (ModelState.IsValid)
{
db.Products.Add(product);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(product);
}
当.Add和.SaveChanges真的需要在我的存储库中时......
每次我想创建那些东西时,我都不想编写50个CRUD操作或复制和粘贴视图和控制器......有没有办法自动化
可能是这样的:
namespace WebApplication.Domain.Abstract
{
public interface IProductRepository
{
IQueryable<Product> Products { get; }
Product Create(Product product);
... yada yada crud operations
}
}
public class EFProductRepository : IProductRepository
{
private EFDbContext context = new EFDbContext();
public IQueryable<Product> Products
{
get { return context.Products; }
}
//... implements all the CRUD operations that entity framework ends up placing inside the controller
}
答案 0 :(得分:0)
通用Repository<TPoco>
是此处的一般方法。
即1个存储库重用于每个POCO。
它还常用于工作单元模式,以将更新组合到逻辑工作单元中。
这是一个基本的演示来说明这一点。
但理想情况下,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;
}
}
}
}
答案 1 :(得分:0)
因为根据评论,这就解决了这个问题:
Visual Studio为基于模板的代码生成提供了内置方法。它被称为T4,您可以阅读更多相关信息here。