有什么不对劲的,我真的需要帮助。所以我有两个问题:
1-当前的代码有什么问题吗? Ive是否正确应用模式?有什么建议或意见,会导致我走向正确的方向?
2-为什么这个代码实际上连接到数据库,创建它,但即使我执行正确的操作也不支持插入? (有关此错误的详细信息,请查看帖子的结尾)** FIXED **
我相信这也可以帮助别人,因为我没有找到足够的信息,以使正确的东西。我很确定很多人都试图以正确的方式做到这一点,如果我正在做的事情是对的,那么我不知道如何。
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接口:
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'
我在做正确的事情吗? ive建造有什么问题吗?
另外如果你有关于我发布的代码的推荐,我会很高兴。我只是想在MVC 3中学习正确的方式来构建任何类型的应用程序。我想要一个很好的开始。
我用 :
>实体框架4与代码优先
> ASP.NET MVC 3
>作为DI容器的NINject
> sql Server Express(不是R2)
> Visual Studio 2010 Web Express
非常感谢您的帮助!
解决方法
我发现第二个问题的解决方案是与错误相关的,发现该ninject实际上拍摄了DatabaseFactory的两个实例,一个用于存储库,另一个用于工作单元。其实这个错误不是问题。这是对象数据库中的内部错误,但正常情况下,我认为自从使用实体框架。
真正的问题是Ninject绑定了两个不同的IDatabaseFactory实例,导致2个连接打开。
该审查已添加到_reviewRepostory中第一个使用数据库的第一个实例的集合。
当在工作单元上调用commit时,它没有保存任何内容,这是因为该事件不在该数据库实例上。事实上,这个工作单元称为数据库,它导致创建一个新的实例,因为ninject发送了一个新的实例。
要解决它,只需使用:
Bind<IDatabaseFactory>().To<DatabaseFactory>().InSingletonScope();
代替
Bind<IDatabaseFactory>().To<DatabaseFactory>();
现在所有的系统正常工作!
现在,对于第一个问题,我会喜欢一些答案,那就是我现在的代码有什么问题吗? Ive是否正确应用模式?有什么建议可以引导我走向正确的方向?