Ninject путаница UnitOfWork

Я все время использую Ninject со своими приложениями MVC 3, но я пытаюсь изменить шаблон для своих объектов данных, чтобы использовать UnitOfWork, и у меня возникают проблемы с выяснением того, как заставить Ninject правильно обрабатывать это.

Я знаю, что моя реализация классов работает, когда они создаются вручную в моем консольном приложении следующим образом:

IDatabaseFactory factory = new DatabaseFactory();
IUnitOfWork worker = new UnitOfWork(factory);
IBlogCategoryDao dao = new BlogCategoryDao(factory);
IBlogCategoryService service = new BlogCategoryService(dao);

BlogCategory category = service.GetById(id);

try
{
    if (category != null)
    {
    service.Delete(category);
    worker.Commit();
    Console.WriteLine("Category deleted successfully!");
    }
    else
    {
    Console.WriteLine("Entity doesn't exist.");
    }
}
catch (Exception ex)
{
    Console.WriteLine("Error deleting category: {0}", ex.Message);
}

В моем приложении MVC 3 я использую пакет NuGet Ninject.MVC3, и это находится в методе RegisterServices.

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IDatabaseFactory>().To<DatabaseFactory>();
    kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();

    kernel.Bind<IBlogCategoryDao>().To<BlogCategoryDao>();
    kernel.Bind<IBlogDao>().To<BlogDao>();

    kernel.Bind<IBlogCategoryService>().To<BlogCategoryService>();
    kernel.Bind<IBlogService>().To<BlogService>();
} 

Хотя это работает по большей части, запросы Get, все запросы POST (Insert, Update, Delete) не выполняются. Исключение не выдается, и когда я прохожу через него, он без проблем проходит через метод SaveChanges() и возвращается обратно в стек, но ничего не выполняется. Итак, я знаю, что мне что-то не хватает в моей конфигурации Ninject.

Вот мой класс Unit of Work.

public class UnitOfWork : IUnitOfWork
{
    private Database _database;  <-- DbContext derived class

    private readonly IDatabaseFactory _databaseFactory;

    public UnitOfWork(IDatabaseFactory databaseFactory)
    {
        this._databaseFactory = databaseFactory;
    }

    public Database Database
    {
        get
        {
            return _database ?? (_database = _databaseFactory.Get());
        }
    }

    public void Commit()
    {
        Database.Commit();
    }
}

Вот класс DatabaseFactory:

public class DatabaseFactory : Disposable, IDatabaseFactory
{
    private Database _database;

    public DatabaseFactory()
    {

    }

    public virtual Database Get()
    {
        if (_database == null)
        {
            _database = DataObjectFactory.CreateContext();
        }

        return _database;
    }

    protected override void DisposeCore()
    {
        if (_database != null)
        {
            _database.Dispose();
        }
    }
}

И мой класс DataObjectFactory:

public static class DataObjectFactory
{
    private static readonly string _connectionString;

    /// <summary>
    /// Static constructor. Reads the connectionstring from web.config just once.
    /// </summary>
    static DataObjectFactory()
    {
        string connectionStringName = ConfigurationManager.AppSettings.Get("ConnectionStringName");
        _connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
    }

    /// <summary>
    /// Creates the Context using the current connectionstring.
    /// </summary>
    /// <remarks>
    /// Gof pattern: Factory method. 
    /// </remarks>
    /// <returns>Action Entities context.</returns>
    public static Database CreateContext()
    {
        return new Database(_connectionString);
    }
}

Это аналогичный шаблон, который используется в приложении EFMVC CodePlex, но я не использую AutoFac.

Любые мысли по этому поводу приветствуются.

Спасибо.


person Kahanu    schedule 09.05.2012    source источник
comment
Что такое база данных? Это кажется слишком сложным.   -  person Erik Funkenbusch    schedule 09.05.2012
comment
База данных является производным классом от DbContext. Он содержит свойства IDbSet‹Blog›.   -  person Kahanu    schedule 09.05.2012
comment
Я на самом деле заставил его работать, немного рефакторинг. Я полностью удалил класс DatabaseFactory и вместо этого добавляю конкретные классы Repository (BlogCategoryDao) с экземпляром UnitOfWork. BlogCategoryDao(IUnitOfWork). Это работает намного лучше и чище, и это действительно работает!   -  person Kahanu    schedule 09.05.2012


Ответы (1)


Я просто делаю это:

kernel.Bind<IUnitOfWork>.To<EFUnitOfWork>().InRequestScope();

EFUnitOfWork.cs

public class EFUnitOfWork : DbContext, IUnitOfWork
{
    // your normal DbContext plus your IUnitOfWork members that delegate to EF context
}

Поскольку EF уже реализует форму Unit Of Work, это позволяет вам использовать для него более общий интерфейс и легко внедрять его.

Кроме того, вы можете реализовать конструкторы EF для строк подключения и просто передать их базовым конструкторам. Затем вы можете использовать Ninject .WithConstructorArgument() для настройки строки подключения с помощью кода AppSettings.

person Erik Funkenbusch    schedule 09.05.2012
comment
Я не вижу расширения .InRequestContext(). Вы имеете в виду .InRequestScope()? У меня это включено, и это все еще не работает. - person Kahanu; 09.05.2012
comment
@ Кахану - да, извини, неправильно запомнил. - person Erik Funkenbusch; 09.05.2012
comment
Я столкнулся с очень похожей проблемой, и я только что добавил InRequestScope к привязке DbFactory в ядре ninject. - person Jean Jimenez; 30.07.2013