1

我已经在我的web应用程序中使用通用服务和存储库构建进行了分层设计。我想先使用代码,这样我就可以编写我的实体,然后创建/更新我的数据库。然而,我似乎无法得到它的工作。我不熟悉代码第一个概念,生成数据库并播种它,所以它可能很明显;-)数据库未更新使用存储库模式和EF代码优先

我的应用程序设计如下。

  • 网站
  • Website.DAL
  • Website.TESTS(尚未使用)

的website.DAL项目包含我的通用服务和存储库,以及DataContext的和我的实体。这个想法是,我可以在我的某个实体的控制器中实例化一个泛型的服务。该服务可以包含更多功能来执行计算等。而存储库仅用于处理CRUD操作。该网站项目的项目有一个参考Website.DAL项目,并且EF5也通过NuGet安装在两个项目中。

DataContext的是这样的:

using System.Data.Entity; 
using System.Web; 
using Website.DAL.Entities; 

namespace Website.DAL.Model 
{ 
    public class MyContext : DbContext 
    { 
     public IDbSet<Project> Projects { get; set; } 
     public IDbSet<Portfolio> Portfolios { get; set; } 

     /// <summary> 
     /// The constructor, we provide the connectionstring to be used to it's base class. 
     /// </summary> 
     public MyContext() 
      : base("MyConnectionstringName") 
     { 
      //MyContext.Database.Initialize(true); 

      //if (HttpContext.Current.IsDebuggingEnabled) 
      //{ 
      // //Database.SetInitializer<MyContext>(new DatabaseInitializer()); 
      // Database.SetInitializer<MyContext>(null); 
      //} 
      //else 
      //{ 
      // //Database.SetInitializer<MyContext>(new CreateInitializer()); 
      //} 
     } 

     static MyContext() 
     { 
      Database.SetInitializer<MyContext>(null); 
     } 

     /// <summary> 
     /// This method prevents the plurarization of table names 
     /// </summary> 
     /// <param name="modelBuilder"></param> 
     protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
      base.OnModelCreating(modelBuilder); 
      modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>(); 
     } 

     //public void Seed(MyContextContext) 
     //{ 
     // // Normal seeding goes here 

     // Context.SaveChanges(); 
     //} 
    } 
} 

我还创建了一个DatabaseInitialiser类,这是目前空,但这个想法ofcourse是让种子我的数据库它创建或更新时。

的DatabaseInitialiser类看起来像这样:

using System.Data.Entity; 
using Website.DAL.Model; 

namespace Website.DAL 
{ 
    public class DatabaseInitializer : DropCreateDatabaseIfModelChanges<MyContext> 
    { 
     public DatabaseInitializer() 
     { 

     }    

     protected override void Seed(MyContextcontext) 
     { 
      //TODO: Implement code to seed database 

      //Save all changes 
      context.SaveChanges(); 
     } 
    } 
} 

由于GenericService是不相关的问题,我会离开它,因为它是唯一currenlty制作到存储库中直接调用,没有任何具体的业务情报。

使用的通用存储库看起来像这样。这里仍然需要改进,但现在起作用。

GenericRepository

using System; 
using System.Collections.Generic; 
using System.Data.Entity; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Text; 
using System.Threading.Tasks; 
using Website.DAL.Model; 
using Website.DAL.RepositoryInterfaces; 

namespace Website.DAL.Repositories 
{ 

    public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class 
    { 
     #region Implementation of IRepository<TEntity> 

     //protected SceObjectContext DataContext; 
     //protected ObjectContext DataContext; 
     private MyContext _context; 
     //private IObjectSet<T> ObjectSet; 
     private DbSet<TEntity> _dbSet; 

     public GenericRepository() 
     { 
      //DataContext = SceObjectContext.Current; 
      //DataContext = new ObjectContext("dbConnection"); 
      _context = new MyContext(); 
      //ObjectSet = DataContext.CreateObjectSet<T>(); 
      _dbSet = _context.Set<TEntity>(); 
     } 

     /// <summary> 
     /// Inserts a new object into the database 
     /// </summary> 
     /// <param name="entity">The entity to insert</param> 
     public void Insert(TEntity entity) 
     { 
      //var entitySetName = GetEntitySetName(typeof(T)); 
      //DataContext.AddObject(entitySetName, entity); 
      _dbSet.Add(entity); 
     } 

     /// <summary> 
     /// Deletes the specified entity from the database 
     /// </summary> 
     /// <param name="entity">The object to delete</param> 
     public void Delete(TEntity entity) 
     { 
      //DataContext.DeleteObject(entity); 
      if (_context.Entry(entity).State == System.Data.EntityState.Detached) 
      { 
       _dbSet.Attach(entity); 
      } 

      _dbSet.Remove(entity); 
     } 

     /// <summary> 
     /// Saves all pending chances to the database 
     /// </summary> 
     public void Save() 
     { 
      _context.SaveChanges(); 
     } 

     /// <summary> 
     /// Retrieves the first object matching the specified query. 
     /// </summary> 
     /// <param name="where">The where condition to use</param> 
     /// <returns>The first matching object, null of none found</returns> 
     public TEntity First(Expression<Func<TEntity, bool>> @where) 
     { 
      return _dbSet.FirstOrDefault(where); 
     } 

     /// <summary> 
     /// Gets a list of all objects 
     /// </summary> 
     /// <returns>An strong typed list of objects</returns> 
     public IEnumerable<TEntity> GetAll() 
     { 
      return _dbSet.AsEnumerable<TEntity>(); 
     } 

     /// <summary> 
     /// Returns ans iQueryable of the matching type 
     /// </summary> 
     /// <returns>iQueryable</returns> 
     public IQueryable<TEntity> AsQueryable() 
     { 
      return _dbSet.AsQueryable(); 
     } 
     #endregion 
    } 
} 

我有我已经创建了两个实体。投资组合是其中之一,显示在下面。项目是第二个,它只是一个简单的POCO类,有一个Id和一些属性。

Portfolio.cs

public class Portfolio 
{ 
    [Key] 
    public Guid Id { get; set; } 
    public String Name { get; set; } 
    public DateTime StartDate { get; set; } 
    public DateTime? EndDate { get; set; } 
    public bool IsPublished { get; set; } 

    public virtual ICollection<Project> Projects { get; set; } 
} 

所有类以上保持在我的Website.DAL项目。我的网站项目中的Global.asax包含一些调用初始化程序的代码,据我所知,应该确保在不久的将来可以完成播种并维护数据库表。

的Global.asax

try 
{ 
    //Regenerate database if needed. 
    //Database.SetInitializer<MyContext>(new DropCreateDatabaseIfModelChanges<MyContext>()); 
    //Database.SetInitializer(new DatabaseInitializer()); 
    Database.SetInitializer(new DropCreateDatabaseIfModelChanges<BorloContext>()); 
    //Database.SetInitializer<MyContext>(new MigrateDatabaseToLatestVersion<MyContext>()); 
} 
catch (Exception) 
{ 
    throw; 
} 

只是为了它的缘故我已经得到了我的HomeController一段代码,它应该得到的所有投资组合项目的ID。

var list = _portfolioService.GetAll(); 

在通过代码进行调试时发生以下情况;

  • Global.asax中的初始化代码通行证。
  • databaseinitialiser的构造函数调用
  • homecontroller中的代码不会引发异常。但是,在将手表添加到'_portfolioService.GetAll()'的调用中时'我收到以下例外;

enter image description here

我也弄不清是怎么回事错在这里。当然,例外情况不好,但我不能查看内部例外,因为它没有给我一个例外。我能做些什么才能做到这一点?或者不是我想要实现的事情不可能,DAL层应该合并到网站中以使代码生成工作?

更新1:

好吧,我已经改变了下面一行在我的上下文

Database.SetInitializer<MyContext>(null); 

Database.SetInitializer<MyContext>(new DatabaseInitializer()); 

现在,我得到这个错误和堆栈跟踪时调试'_portfolioService.GetAll();'调用HomeController的

错误:

Model compatibility cannot be checked because the database does not contain model metadata. Model compatibility can only be checked for databases created using Code First or Code First Migrations.

bij System.Data.Entity.Internal.ModelCompatibilityChecker.CompatibleWithModel(InternalContext internalContext, ModelHashCalculator modelHashCalculator, Boolean throwIfNoMetadata) 
    bij System.Data.Entity.Internal.InternalContext.CompatibleWithModel(Boolean throwIfNoMetadata) 
    bij System.Data.Entity.Database.CompatibleWithModel(Boolean throwIfNoMetadata) 
    bij System.Data.Entity.DropCreateDatabaseIfModelChanges`1.InitializeDatabase(TContext context) 
    bij System.Data.Entity.Database.<>c__DisplayClass2`1.<SetInitializerInternal>b__0(DbContext c) 
    bij System.Data.Entity.Internal.InternalContext.<>c__DisplayClass8.<PerformDatabaseInitialization>b__6() 
    bij System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action) 
    bij System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization() 
    bij System.Data.Entity.Internal.LazyInternalContext.<InitializeDatabase>b__4(InternalContext c) 
    bij System.Data.Entity.Internal.RetryAction`1.PerformAction(TInput input) 
    bij System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action`1 action) 
    bij System.Data.Entity.Internal.LazyInternalContext.InitializeDatabase() 
    bij System.Data.Entity.Internal.InternalContext.Initialize() 
    bij System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) 
    bij System.Data.Entity.Internal.Linq.InternalSet`1.Initialize() 
    bij System.Data.Entity.Internal.Linq.InternalSet`1.GetEnumerator() 
    bij System.Data.Entity.Infrastructure.DbQuery`1.System.Collections.Generic.IEnumerable<TResult>.GetEnumerator() 
    bij System.Linq.SystemCore_EnumerableDebugView`1.get_Items() 
+0

哈! “**执行命令定义时发生错误... **”回答您的问题并不容易,至少不是非荷兰语的用户:)我不得不从您的屏幕截图中输入荷兰语消息谷歌翻译。消息中是否有一些有趣的内容?它截图中的截图... – Slauma

+0

@Slauma,对不起。将翻译错误和更新问题:) – Rob

+0

@Slauma,请参阅更新1后的意见:) – Rob

回答

0

由于没有其他的解决方案来过我决定改变我的做法。

我自己首先创建了数据库,并确保正确的SQL用户已配置,并且有权访问。

然后我从Global.asax文件中删除了初始值设定项和代码。之后,我在包管理器控制台中运行了以下命令(因为分层设计我不得不在控制台中选择正确的项目);

Enable-Migrations 

在启用迁移后,我对我的实体进行了一些最后更改,我运行下面的命令以支持新的迁移;

Add-Migration AddSortOrder 

创建我的迁移后,我在控制台中运行了以下命令,并且瞧,数据库被我的实体更新;

Update-Database -Verbose 

为了能够运行迁移我已经覆盖了种子法在我Configuraton.cs类,这是使迁移时创建,当种子数据库。这种方法的最终代码就是这样的;

protected override void Seed(MyContext context) 
     { 
      // This method will be called after migrating to the latest version. 

      //Add menu items and pages 
      if (!context.Menu.Any() && !context.Page.Any()) 
      { 
       context.Menu.AddOrUpdate(new Menu() 
              { 
               Id = Guid.NewGuid(), 
               Name = "MainMenu", 
               Description = "Some menu", 
               IsDeleted = false, 
               IsPublished = true, 
               PublishStart = DateTime.Now, 
               LastModified = DateTime.Now, 
               PublishEnd = null, 
               MenuItems = new List<MenuItem>() 
                   { 
                    new MenuItem() 
                     { 
                      Id = Guid.NewGuid(), 
                      IsDeleted = false, 
                      IsPublished = true, 
                      PublishStart = DateTime.Now, 
                      LastModified = DateTime.Now, 
                      PublishEnd = null, 
                      Name = "Some menuitem", 
                      Page = new Page() 
                         { 
                          Id = Guid.NewGuid(), 
                          ActionName = "Some Action", 
                          ControllerName = "SomeController", 
                          IsPublished = true, 
                          IsDeleted = false, 
                          PublishStart = DateTime.Now, 
                          LastModified = DateTime.Now, 
                          PublishEnd = null, 
                          Title = "Some Page" 
                         } 
                     }, 
                    new MenuItem() 
                     { 
                      Id = Guid.NewGuid(), 
                      IsDeleted = false, 
                      IsPublished = true, 
                      PublishStart = DateTime.Now, 
                      LastModified = DateTime.Now, 
                      PublishEnd = null, 
                      Name = "Some MenuItem", 
                      Page = new Page() 
                         { 
                          Id = Guid.NewGuid(), 
                          ActionName = "Some Action", 
                          ControllerName = "SomeController", 
                          IsPublished = true, 
                          IsDeleted = false, 
                          PublishStart = DateTime.Now, 
                          LastModified = DateTime.Now, 
                          PublishEnd = null, 
                          Title = "Some Page" 
                         } 
                     } 
                   } 
              }); 
      } 

      if (!context.ComponentType.Any()) 
      { 
       context.ComponentType.AddOrUpdate(new ComponentType() 
       { 
        Id = Guid.NewGuid(), 
        IsDeleted = false, 
        IsPublished = true, 
        LastModified = DateTime.Now, 
        Name = "MyComponent", 
        PublishEnd = null, 
        PublishStart = DateTime.Now 
       }); 
      } 


      try 
      { 
       // Your code... 
       // Could also be before try if you know the exception occurs in SaveChanges 

       context.SaveChanges(); 
      } 
      catch (DbEntityValidationException e) 
      { 
       //foreach (var eve in e.EntityValidationErrors) 
       //{ 
       // Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:", 
       //  eve.Entry.Entity.GetType().Name, eve.Entry.State); 
       // foreach (var ve in eve.ValidationErrors) 
       // { 
       //  Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"", 
       //   ve.PropertyName, ve.ErrorMessage); 
       // } 
       //} 
       //throw; 

       var outputLines = new List<string>(); 
       foreach (var eve in e.EntityValidationErrors) 
       { 
        outputLines.Add(string.Format(
         "{0}: Entity of type \"{1}\" in state \"{2}\" has the following validation errors:", 
         DateTime.Now, eve.Entry.Entity.GetType().Name, eve.Entry.State)); 
        foreach (var ve in eve.ValidationErrors) 
        { 
         outputLines.Add(string.Format(
          "- Property: \"{0}\", Error: \"{1}\"", 
          ve.PropertyName, ve.ErrorMessage)); 
        } 
       } 
       System.IO.File.AppendAllLines(@"c:\temp\errors.txt", outputLines); 
       throw; 
      } 
     } 

目前的缺点是我必须在包管理器控制台中手动迁移(仅)2个命令。但是同时,这种情况不会动态发生也是很好的,因为这样可以防止对我的数据库进行可能不需要的更改。进一步的一切都很完美。

相关问题