ASP.Net MVC - «Не удается создать экземпляр интерфейса» - PullRequest
2 голосов
/ 07 февраля 2011

Я уже некоторое время пытаюсь решить эту проблему, и я зашел в тупик, так что, возможно, вы, ребята, можете помочь.Обратите внимание, что это не связано с этим вопросом.

Я использую Entity-Code First в MVC3.Я, должно быть, сделал что-то хитрое с одним из моих объектов, потому что когда он впервые пытается создать базу данных и заполнить ее из моей функции Seed, возникает эта ошибка (функция Seed фактически никогда не вызывается, но база данных итаблицы созданы).

Исключение выдается глубоко в системе:

>   mscorlib.dll!System.RuntimeType.CreateInstanceSlow(bool publicOnly, bool skipCheckThis, bool fillCache = true) + 0x63 bytes 
    mscorlib.dll!System.Activator.CreateInstance(System.Type type, bool nonPublic) + 0x46 bytes 
    System.Web.Mvc.dll!System.Web.Mvc.DependencyResolver.DefaultDependencyResolver.GetService(System.Type serviceType) + 0x25 bytes 
    System.Web.Mvc.dll!System.Web.Mvc.DependencyResolverExtensions.GetService<System.Web.Mvc.IControllerFactory>(System.Web.Mvc.IDependencyResolver resolver) + 0x3d bytes  
    System.Web.Mvc.dll!System.Web.Mvc.SingleServiceResolver<System.Web.Mvc.IControllerFactory>.Current.get() + 0x7e bytes   
    System.Web.Mvc.dll!System.Web.Mvc.MvcRouteHandler.GetSessionStateBehavior(System.Web.Routing.RequestContext requestContext = {System.Web.Routing.RequestContext}) + 0x72 bytes  
    System.Web.Mvc.dll!System.Web.Mvc.MvcRouteHandler.GetHttpHandler(System.Web.Routing.RequestContext requestContext = {System.Web.Routing.RequestContext}) + 0x2a bytes   
    System.Web.Mvc.dll!System.Web.Mvc.MvcRouteHandler.System.Web.Routing.IRouteHandler.GetHttpHandler(System.Web.Routing.RequestContext requestContext) + 0xb bytes 
    System.Web.dll!System.Web.Routing.UrlRoutingModule.PostResolveRequestCache(System.Web.HttpContextBase context = {System.Web.HttpContextWrapper}) + 0x108 bytes  
    System.Web.dll!System.Web.Routing.UrlRoutingModule.OnApplicationPostResolveRequestCache(object sender, System.EventArgs e) + 0x57 bytes 
    System.Web.dll!System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() + 0x95 bytes   
    System.Web.dll!System.Web.HttpApplication.ExecuteStep(System.Web.HttpApplication.IExecutionStep step = {System.Web.HttpApplication.SyncEventExecutionStep}, ref bool completedSynchronously = true) + 0x4c bytes    
    System.Web.dll!System.Web.HttpApplication.ApplicationStepManager.ResumeSteps(System.Exception error) + 0x13e bytes  
    System.Web.dll!System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext context, System.AsyncCallback cb, object extraData) + 0xad bytes  
    System.Web.dll!System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest wr = {Microsoft.VisualStudio.WebHost.Request}) + 0x1a2 bytes  
    System.Web.dll!System.Web.HttpRuntime.ProcessRequestNoDemand(System.Web.HttpWorkerRequest wr) + 0x7d bytes  
    System.Web.dll!System.Web.HttpRuntime.ProcessRequest(System.Web.HttpWorkerRequest wr) + 0x47 bytes  
    WebDev.WebHost40.dll!Microsoft.VisualStudio.WebHost.Request.Process() + 0x17b bytes 
    WebDev.WebHost40.dll!Microsoft.VisualStudio.WebHost.Host.ProcessRequest(Microsoft.VisualStudio.WebHost.Connection conn = {System.Runtime.Remoting.Proxies.__TransparentProxy}) + 0x6c bytes 
    [Appdomain Transition]  
    WebDev.WebHost40.dll!Microsoft.VisualStudio.WebHost.Server.OnSocketAccept(object acceptedSocket) + 0x83 bytes   
    mscorlib.dll!System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(object state) + 0x2d bytes 
    mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool ignoreSyncCtx) + 0xb0 bytes    
    mscorlib.dll!System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() + 0x5a bytes 
    mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch() + 0x147 bytes  
    mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() + 0x2d bytes    
    [Native to Managed Transition]  

У меня только один объект на данный момент.Обратите внимание, как я уже говорил ранее, он создан в базе данных:

// class Category
public class Category
{
    [Key]
    public int CategoryID { get; set; }

    [Required]
    [StringLength(64)]
    public string Name { get; set; }

    public int? ParentCategoryID { get; set; }
    [ForeignKey("ParentCategoryID")]
    public Category ParentCategory { get; set; }

    [Required]
    public int ListOrder { get; set; }

    // left/right
    public int TreeLeft { get; set; }
    public int TreeRight { get; set; }
}   // eo class Category

Это мой DbContext класс:

// class ModelContext
public class ModelContext : DbContext
{
    public DbSet<Models.CMS.Category> ContentCategories { get; set; }

    // property to get the object context
    public ObjectContext ObjectContext
    {
        get
        {
            return ((IObjectContextAdapter)this).ObjectContext;
        }
    }


    // OnModelCreating
    protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
    {

        base.OnModelCreating(modelBuilder);
    }   // eo OnModelCreating

}   // eo class ModelContext

Не так многопроисходит там.И наконец, мой инициализатор.Функция Seed никогда не вызывается:

// class ModelInitializer
public class ModelInitializer : DropCreateDatabaseIfModelChanges<ModelContext>
{
    // seed
    protected override void Seed(ModelContext context)
    {
        var catRepo = Models.CMS.CategoryRepository.Instance;

        // Root category node
        context.ContentCategories.Add(catRepo.CreateRoot());

        // Test data
        Category home = catRepo.Add(new Category { Name = "Home", ListOrder = 10 });
        Category news = catRepo.Add(new Category { Name = "News", ListOrder = 20 });

        catRepo.Add(new Category { Name = "Current News", ListOrder = 10 }, news);
        catRepo.Add(new Category { Name = "Older News", ListOrder = 20 }, news);
    }   // eo Seed

}   // eo class ModelInitializer

Вам может потребоваться или нет дополнительная информация, и я предоставлю ее, очевидно.Понятия не имею, с чего начать искать.Ошибка может быть даже не связана с моими моделями, но в любом случае.Я отмечаю, что это происходит в MvcRouteHandler, я ничего особенного здесь не сделал, и если я проигнорирую исключение, я попаду в свой обработчик действий для HomeController.Я получаю сообщение об ошибке, потому что база данных не заполнена (поскольку Seed никогда не вызывался).

О, и если это поможет, инициализатор в global.asax.cs:

    protected void Application_Start()
    {
        DbDatabase.SetInitializer<ModelContext>(new ModelInitializer());

        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    }

Любая помощь или указатели будут оценены!

РЕДАКТИРОВАТЬ: контроллер выглядит следующим образом:

    public ActionResult Index()
    {
        Models.CMS.CategoryRepository repo = Models.CMS.CategoryRepository.Instance;
        List<Models.CMS.Category> cats = repo.GetAll();
        return View();
    }

Ошибка происходит до , однако он попадает в этот обработчик.Некоторый код в этом вызове GetAll() получает ошибку, поскольку база данных не заполнена (инициализатор никогда не вызывался).

1 Ответ

1 голос
/ 07 февраля 2011

Я скачал проект. Во-первых, чтобы начать все заново без каких-либо проблем с моделью, я установил ModelInitializer для наследования от DropCreateDatabaseAlways, потому что я не хочу, чтобы устаревшие данные в базе данных появлялись при каждой отладке.

Когда я запускал приложение, я получал нулевое исключение в методе Add() CategoryRepository. Я думаю, что у вас может быть неправильное понимание шаблона хранилища. В настоящее время вы используете статический репозиторий, что плохо для ИМО. Вы также создаете новый контекст модели в нескольких местах, чего следует избегать, передавая его в хранилище в качестве параметра. В идеале ваш интерфейс для хранилища категорий должен выглядеть примерно так:

public interface ICategoryRepository
{
    void Add(Category category);
    void Remove(Category category);
    List<Category> GetAll(int parentId = 0);
    Category GetRoot();
    Category Get(int id);
}

Тогда внутри вашей реализации хранилища будет что-то вроде этого:

public class CategoryRepository : ICategoryRepository
{
    private readonly ModelContext context;

    // Here we pass in the context so that it can be used by methods.
    public CategoryRepository(ModelContext context)
    {
        this.context = context;
    }

    #region ICategoryRepository Members

    public void Add(Category category, Category parent = null)
    {

        if (parent == null)
        {
            parent = this.GetRoot();
        }
        // Snipped the stuff here.

        // Finally add to the current context.
        this.context.ContentCategories.Add(category);
    }

    // And all other methods...
}

Я внес некоторые существенные изменения в проект, поэтому надеюсь, что они имеют смысл для шаблона хранилища. Вы можете найти обновленный проект здесь . После того, как я изменил это, я получил исключение об отношениях - поэтому я думаю, что вам лучше всего будет объяснить, как вы пытаетесь смоделировать категории (некоторая форма древовидной структуры ...), и я могу помочь вам оттуда. Кроме того, обязательно очистите ваш проект и убедитесь, что база данных пуста. Ура!

...