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個命令。但是同時,這種情況不會動態發生也是很好的,因爲這樣可以防止對我的數據庫進行可能不需要的更改。進一步的一切都很完美。

相關問題