0

У меня есть приложение MVC4 с использованием RavenDB в качестве хранилища данных. Приложение имеет уровни MVC/Web, Domain, Data и Security.Как сделать RavenDB DocumentStore доступным для вызовов API

Я пишу пользовательские поставщики членства и роли, которым необходимо инициализировать базу данных и получить доступ к DocumentStore. Я пишу этот класс с уровня безопасности и хотел бы использовать singleton DocumentStore (установленный в приложении), но я не могу понять, как получить к нему доступ.

Другие примеры, которые я вижу в написании пользовательских поставщиков для RavenDB, создают новые экземпляры DocumentStore в методах Provider.Initialize(), но это, похоже, нарушает правило наличия единого DocumentStore на сервер.

В настоящее время я создаю один экземпляр RavenDB DocumentStore в Application_Start(). У меня есть базовый контроллер на уровне MVC/Web, который обрабатывает DocumentStore.Session (s).

Есть ли способ сделать это? Должен ли я переместить логику безопасности в уровень MVC/Web, чтобы упростить ситуацию?

ответ

0

Я придумал мое собственное решение, используя одноэлементный шаблон.

Что я сделал, это создать одноэлементный объект, который предоставляет публичное свойство IDocumentStore в слое данных моего приложения. Он использует статический конструктор, который запускается при первом запросе на статическое свойство (выполняется в Application_Start) и в свою очередь создает экземпляр объекта IDocumentStore. Первый экземпляр затем затем возвращается для каждой ссылки на DocStore.Instance в базовом контроллере и в других слоях моего приложения (например, на уровне безопасности f.ex.)

public sealed class DocStore 
{ 
    protected static readonly IDocumentStore instance; 

    static DocStore() 
    { 
     // instantiate documentStore 
     instance = new DocumentStore { ConnectionStringName = Constants.ConnectionStrings.XXXXX }; 
     instance.Initialize(); 

     // instantiate tenants 
     try 
     { 
      instance.DatabaseCommands.EnsureDatabaseExists(Constants.Tenants.XXXXX); 
     } 
     catch (Exception ex) 
     { 

      //TODO: catch exception 
      throw ex; 
     } 

     // initialize indexed 
     try 
     { 
      InitializeIndexes(instance); 
     } 
     catch (Exception ex) 
     { 

      //TODO: catch exception 
      throw ex; 
     } 
    } 

    private DocStore() 
    { 

    } 

    public static IDocumentStore Instance 
    { 
     get { return instance; } 
    } 

    private static void InitializeIndexes(IDocumentStore store) 
    { 
     // builds all indexes defined in XXXXX.Data.dll 
     var dataCatalog = new CompositionContainer(new AssemblyCatalog(typeof(DocStore).Assembly)); 
     IndexCreation.CreateIndexes(dataCatalog, 
            store.DatabaseCommands.ForDatabase(Constants.Tenants.XXXXX), 
            store.Conventions); 
    } 
} 
1

Возможно, вы захотите использовать какую-либо инъекцию зависимостей, используя автоматические инструменты, такие как TinyIoC, или сделав это вручную.

Например, посмотрите, как это делает RaccoonBlog. Во-первых, он создает экземпляр DocumentStore в Application_Start, и магазины, которые ссылаются на статические переменные различных базовых классов:

https://github.com/ayende/RaccoonBlog/blob/master/RaccoonBlog.Web/Global.asax.cs#L66

Затем он вводит новый объект Session всякий раз, когда начинается новый сеанс:

https://github.com/ayende/RaccoonBlog/blob/master/RaccoonBlog.Web/Global.asax.cs#L31

И этот пункт тянет от контроллера базового класса:

https://github.com/ayende/RaccoonBlog/blob/master/HibernatingRhinos.Loci.Common/Controllers/RavenController.cs#L16

Я бы сделал это немного лучше, используя правильный IoC или, по крайней мере, без использования словаря Items, но вы поняли суть.

Просто держать DocumentStore где общественность и ввести открытые сессии для базовых классов

+0

благодарит за synhershko ответа. Это кажется жизнеспособным, но я уже реализовал решение, когда увидел ваш ответ. Это очень похоже (минус DI). [Смотри ниже] –