实体框架构建视图和控制器......我必须重新进入我的存储库

时间:2013-12-10 00:16:24

标签: c# entity-framework visual-studio-2013

实体框架是否有一些自动化的功能,这意味着我不必重新编写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
}

2 个答案:

答案 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