Использование SolrNet для запроса Solr из консольного приложения?

Я пытаюсь использовать SolrNet в приложении командной строки (точнее, из LINQPad) для проверки некоторых запросов, и при попытке инициализировать библиотеку я получаю следующую ошибку:

Key 'SolrNet.Impl.SolrConnection.UserQuery+Resource.SolrNet.Impl.SolrConnection' already registered in container

Однако, если я поймаю эту ошибку и продолжу, ServiceLocator выдаст мне следующую ошибку:

Activation error occured while trying to get instance of type ISolrOperations`1, key ""

С внутренним исключением:

The given key was not present in the dictionary.

Мой полный код выглядит так:

try
{
    Startup.Init<Resource>("http://localhost:8080/solr/");
    Console.WriteLine("Initialized\n");
}
catch (Exception ex)
{
    Console.WriteLine("Already Initialized: " + ex.Message);
}

// This line causes the error if Solr is already initialized
var solr = ServiceLocator.Current.GetInstance<ISolrOperations<Resource>>();

// Do the search
var results = solr.Query(new SolrQuery("title:test"));

Я использую Tomcat 7 в Windows 7x64 с установленным Solr 3.4.0.

В StackOverflow есть еще одно сообщение о той же проблеме, хотя принятый ответ о размещении код Startup.Init в Global.asax относится только к ASP.NET.

Перезапуск службы Tomcat7 решает проблему, но необходимость делать это после каждого запроса является проблемой.

Как правильно использовать библиотеку SolrNet для взаимодействия с Solr из консольного приложения C#?


person Mun    schedule 22.02.2012    source источник


Ответы (2)


Правильный способ использования SolrNet в консольном приложении — выполнить только строку

 Startup.Init<Resource>("http://localhost:8080/solr/");

один раз на всю жизнь вашего консольного приложения. Я обычно ставлю его первой строкой в ​​методе Main, как показано ниже...

static void Main(string[] args)
{
     Startup.Init<Resource>("http://localhost:8080/solr/");

     //Call method or do work to query from solr here... 
     //Using your code in a method...
     QuerySolr();
}

private static void QuerySolr()
{
     var solr = ServiceLocator.Current.GetInstance<ISolrOperations<Resource>>();

     // Do the search
     var results = solr.Query(new SolrQuery("title:test"));
}

Ваша ошибка связана с тем, что вы пытаетесь несколько раз инициализировать соединение SolrNet. Вам нужно только инициализировать его один раз при запуске консольного приложения, а затем при необходимости ссылаться (искать) через ServiceLocator.

person Paige Cook    schedule 22.02.2012
comment
Если это так, то не должно ли решить проблему обертывание Startup.Init в блоке try/catch? Таким образом, даже если он вызывался несколько раз и вызывал ошибку «уже зарегистрирован в контейнере», локатор службы все равно сможет получить экземпляр и позволить остальной части кода работать правильно. В настоящее время я запускаю этот код в LINQPad, так что, возможно, это часть проблемы. Я попробую запустить его как стандартное консольное приложение и посмотрю, будет ли это иметь значение. - person Mun; 22.02.2012
comment
Не обязательно, я предполагаю, что когда вы инициализируете его во второй раз, вы искажаете запись и делаете ее непригодной для использования. (Но я не уверен, так как не знаю внутренней работы контейнера IOC ServiceLocator). Следовательно, ошибка активации, которую вы видите при попытке запроса. Поэтому ловить исключение и продолжать, несмотря на это, не получится. - person Paige Cook; 22.02.2012
comment
Я действительно считаю, что запуск в LINQPad может быть частью проблемы, поскольку у меня есть около 10 различных консольных приложений, использующих SolrNet без каких-либо проблем. - person Paige Cook; 22.02.2012
comment
Просмотрел настройки LINQPad, и я думаю, что вы были правы в том, что соединение SolrNet инициализировалось несколько раз. Похоже, что домен приложения используется повторно, что и вызывало это. Перейдите в «Настройки» -> «Дополнительно» и установите для параметра «Всегда использовать свежие домены приложений» значение «истина», похоже, проблема решена (требуется перезапуск LINQPad). Спасибо за вашу помощь. - person Mun; 22.02.2012
comment
@Mun: или просто запустите Startup.Init один раз, затем удалите его из редактора LINQPad, чтобы больше не запускать. - person Mauricio Scheffer; 22.02.2012
comment
@MauricioScheffer Запрос кэшируется только на некоторое время, поэтому код инициализации все равно необходимо запустить, когда LINQPad решит снова загрузить домен приложения. Комментирование и раскомментирование строки кажется чем-то вроде танца, и просто принудительно загрузить новый домен приложения, изменив настройку, кажется гораздо более простым вариантом с минимальными побочными эффектами. - person Mun; 22.02.2012

Мое решение ясно. Запуск перед инициализацией

Startup.Container.Clear();
Startup.InitContainer();
Startup.Init<Resource>("http://localhost:8080/solr/");
person Truc    schedule 16.01.2016
comment
это наиболее полезно для меня, особенно я использую его в LinqPad, чтобы поиграть с запросом. - person YS.; 10.02.2016