我在我的 web 应用程序中进行了分层设计,具有通用服务和存储库构造。我想先使用代码,这样我就可以对我的实体进行编码,然后创建/更新我的数据库。但是我似乎无法让它工作。我是生成数据库并为其播种的代码优先概念的新手,因此它很可能是显而易见的;-)
我的应用程序设计如下。
- 网站
- 网站.DAL
- Website.TESTS(尚未使用)
website.DAL 项目包含我的通用服务和存储库,以及 DataContext 和我的实体。这个想法是我可以在某个实体的控制器内实例化一个泛型服务。该服务可以包含更多功能来进行计算等。存储库仅用于处理 CRUD 操作。网站项目当然参考了 Website.DAL 项目,并且通过 NuGet 在两个项目中安装了 EF5。
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 类,但我的想法当然是在创建或更新数据库时让它成为我的数据库的种子。
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 与问题无关,我将其省略,因为它目前仅直接调用存储库而没有任何特定的商业智能。
使用的通用存储库如下所示。这里的事情仍然需要改进,但它现在有效。
通用存储库
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
}
}
我有两个我创建的实体。投资组合是其中之一,显示在下方。Project 是第二个,它只是一个带有 Id 和一些属性的简单 POCO 类。
投资组合.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 包含一些调用初始化程序的代码,据我所知,它应该确保可以在不久的将来完成播种并维护数据库表。
全球.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();”的调用添加手表时 我收到以下异常;
我无法弄清楚这里出了什么问题。当然异常不好,但我无法查看内部异常,因为它没有给我一个。我能做些什么来让它工作?或者我想要实现的事情不是不可能的,是否应该将 DAL 层合并到网站中以使代码生成工作?
更新 1:
好的,我在我的上下文中更改了以下行
Database.SetInitializer<MyContext>(null);
到
Database.SetInitializer<MyContext>(new DatabaseInitializer());
现在我在调试“_portfolioService.GetAll();”时遇到了这个错误和堆栈跟踪 呼叫家庭控制器
错误:
无法检查模型兼容性,因为数据库不包含模型元数据。只能检查使用 Code First 或 Code First 迁移创建的数据库的模型兼容性。
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()