【发布时间】:2018-06-11 02:11:43
【问题描述】:
我尝试使用上述技术构建一些基础项目。我想要最大的灵活性和可测试性,因此我尝试在此过程中使用模式来将其作为未来项目的基础。然而,似乎 出了点问题或其他什么,我真的需要帮助。所以我有两个问题:
我当前的代码有什么问题吗?我正确地应用了模式?有什么建议或建议可以引导我朝着正确的方向前进吗?
为什么这段代码实际上连接到数据库并创建它,但即使我执行了更正操作也不支持插入? (有关此错误的详细信息,请查看帖子末尾)已修复
我相信这也可以帮助其他人,因为我没有找到足够的信息来正确地弥补一些东西。我很确定很多人都试图以正确的方式做事,但不确定我所做的是否正确。
我有两个实体:评论和评论
评论
public class Comment
{
[Key]
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Author { get; set; }
public virtual string Body { get; set; }
}
评论
public class Review
{
[Key]
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Author { get; set; }
public virtual string Body { get; set; }
public virtual bool Visible { get; set; }
public IEnumerable<Comment> Comments { get; set; }
}
我以这种方式为每个人建立了一个基础存储库:
通用存储库
public abstract class EFRepositoryBase<T> : IRepository<T> where T : class
{
private Database _database;
private readonly IDbSet<T> _dbset;
protected IDatabaseFactory DatabaseFactory { get; private set; }
protected Database Database { get { return _database ?? (_database = DatabaseFactory.Get()); } }
public EFRepositoryBase(IDatabaseFactory databaseFactory)
{
DatabaseFactory = databaseFactory;
_dbset = Database.Set<T>();
}
public virtual void Add(T entity)
{
_dbset.Add(entity);
}
public virtual void Delete(T entity)
{
_dbset.Remove(entity);
}
public virtual T GetById(long id)
{
return _dbset.Find(id);
}
public virtual IEnumerable<T> All()
{
return _dbset.ToList();
}
}
对于具体操作,我使用了一个接口:
public interface IReviewRepository : IRepository<Review> {
// Add specific review operations
IEnumerable<Review> FindByAuthor(string author);
}
所以我从抽象类中获取泛型操作以及特定操作:
public class EFReviewRepository : EFRepositoryBase<Review>, IReviewRepository
{
public EFReviewRepository(IDatabaseFactory databaseFactory)
: base(databaseFactory)
{ }
public IEnumerable<Review> FindByAuthor(string author)
{
return base.Database.Reviews.Where(r => r.Author.StartsWith(author))
.AsEnumerable<Review>();
}
}
如你所见,我还使用数据库工厂来生成数据库上下文:
数据库工厂
public class DatabaseFactory : Disposable, IDatabaseFactory
{
private Database _database;
public Database Get()
{
return _database ?? (_database = new Database(@"AppDb"));
}
protected override void DisposeCore()
{
if (_database != null)
_database.Dispose();
}
}
DISPOSABLE(一些扩展方法...)
public class Disposable : IDisposable
{
private bool isDisposed;
~Disposable()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!isDisposed && disposing)
{
DisposeCore();
}
isDisposed = true;
}
protected virtual void DisposeCore()
{
}
}
数据库
public class Database : DbContext
{
private IDbSet<Review> _reviews;
public IDbSet<Review> Reviews
{
get { return _reviews ?? (_reviews = DbSet<Review>()); }
}
public virtual IDbSet<T> DbSet<T>() where T : class
{
return Set<T>();
}
public Database(string connectionString)
: base(connectionString)
{
//_reviews = Reviews;
}
public virtual void Commit()
{
base.SaveChanges();
}
/*
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// TODO: Use Fluent API Here
}
*/
}
最后,我有我的工作单元......
工作单位
public class UnitOfWork : IUnitOfWork
{
private readonly IDatabaseFactory _databaseFactory;
private Database _database;
public UnitOfWork(IDatabaseFactory databaseFactory)
{
_databaseFactory = databaseFactory;
}
protected Database Database
{
get { return _database ?? (_database = _databaseFactory.Get()); }
}
public void Commit()
{
Database.Commit();
}
}
我还使用 Ninject 绑定了接口:
忍者控制器工厂
public class NinjectControllerFactory : DefaultControllerFactory
{
// A Ninject "Kernel" is the thing that can supply object instances
private IKernel kernel = new StandardKernel(new ReviewsDemoServices());
// ASP.NET MVC calls this to get the controller for each request
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
return null;
return (IController)kernel.Get(controllerType);
}
private class ReviewsDemoServices : NinjectModule
{
public override void Load()
{
// Bindings...
Bind<IReviewRepository>().To<EFReviewRepository>();
Bind<IUnitOfWork>().To<UnitOfWork>();
Bind<IDatabaseFactory>().To<DatabaseFactory>();
Bind<IDisposable>().To<Disposable>();
}
}
}
但是,当我在构造函数中调用时(默认操作)...
public class ReviewController : Controller
{
private readonly IReviewRepository _reviewRepository;
private readonly IUnitOfWork _unitOfWork;
public ReviewController(IReviewRepository postRepository, IUnitOfWork unitOfWork)
{
_reviewRepository = postRepository;
_unitOfWork = unitOfWork;
}
public ActionResult Index()
{
Review r = new Review { Id = 1, Name = "Test", Visible = true, Author = "a", Body = "b" };
_reviewRepository.Add(r);
_unitOfWork.Commit();
return View(_reviewRepository.All());
}
}
这似乎创建了数据库,但没有在 EF4 的数据库中插入任何内容。看来我可能发现了问题..在查看数据库对象时..连接状态已关闭,服务器版本抛出此类异常:
ServerVersion = '(((System.Data.Entity.DbContext (_database)).Database.Connection).ServerVersion' threw an exception of type 'System.InvalidOperationException'
我在做正确的事吗?我建造的东西有什么问题吗?
另外,如果您对我发布的代码有任何建议,我会很高兴。我只是想学习在 MVC 3 中构建任何类型的应用程序的正确方法。我想要一个好的开始。
我用:
Entity Framework 4 with Code-First
ASP.NET MVC 3
Ninject 作为 DI 容器
SQL Server Express(非 R2)
Visual Studio 2010 网络速递
【问题讨论】:
-
你从哪里得到这个关于 Entity 的模式?我有兴趣看看这样的东西。我在 Kazi Manzur Rashid @shrinkr.codeplex.com 编写的收缩器应用程序中看到了类似的模式
-
我认为这段代码最初来自myfinance.codeplex.com
-
没有,我从这个地方周围的其他帖子以及与我交谈过的人那里收集了这个代码,他是该领域的真正专家。我打算把我所有的代码放在这里帮助其他人。
-
您是否有理由暴露您的工作单元,什么时候应该在包含工作单元的存储库中?我希望你调用你的存储库服务来更新、插入和保存... RepositoryService.Insert(entity); RepositoryService.Save();
标签: entity-framework-4 asp.net-mvc-3 ninject