Я довольно новичок в .NET и SharePoint (я пришел из среды Java EE), и у меня возникает следующая странная проблема при работе над SharePoint 2013 .
По сути, в моем приложении SharePoint я получаю доступ к базе данных SQL Server, используя некоторые классы в проекте DAO (что есть в моем решении).Этот проект DAO основан на ADO.NET .Работает нормально.Проблема заключается в том, что я создал новый проект NUnit в своем решении, потому что я хочу протестировать этот метод DAO, определенный в моем проекте DAO, выполняя некоторый интеграционный тест.В этом случае я получаю странное исключение.
Я пытаюсь объяснить вам мою ситуацию в деталях.
В моем решении у меня есть проект, который действует как DAO (он содержит весь запрос базы данныхи обрабатывать соединение с БД).Этот проект называется что-то вроде MyPrjSqlEngine .Затем у меня есть другой проект под названием MyMainPrj , который содержит некоторое задание таймера .В этом основном проекте у меня есть задание таймера, содержащее следующую логику:
namespace MyMainPrj.TimerJob.Notifiche
{
public class NotificheGiornaliereView : SPJobDefinition
{
public NotificheGiornaliereView() : base() { }
public NotificheGiornaliereView(string jobName, SPService service) :
base(jobName, service, null, SPJobLockType.None)
{
this.Title = "Notifiche giornaliere protocollo View";
}
public NotificheGiornaliereView(string jobName, SPWebApplication webapp) :
base(jobName, webapp, null, SPJobLockType.ContentDatabase)
{
this.Title = "Notifiche giornaliere protocollo View";
}
public override void Execute(Guid targetInstanceId)
{
List<string> tenantList = ProtUtils.GetTenantList();
DBConnection dbConfig = new DBConnection();
dbConfig.Tenant = "XXX";
ArrayList listaUtenti = new ArrayList();
List<string> urlList = IndirizziProtocolliSQL.GetListaIndirizziSiti(dbConfig);
}
}
}
Логика реализована в методе Execute () , который извлекает список строк из БД. IndirizziProtocolliSQL является классом моего MyPrjSqlEngine DAO проекта.
Это код вызываемого метода, реализованного в этом проекте DAO:
public static List<string> GetListaIndirizziSiti(DBConnection dbConf)
{
string url = null;
List<string> urlList = new List<string>();
string query = PROT_INDIRIZZI_PROTOCOLLI.SELECT_LISTA_INDIRIZZI_SITI;
using (SqlConnection con = PrjConnection.getStringConnection(dbConf.Tenant + "_PROTOCOLLO"))
{
using (SqlCommand cmd = new SqlCommand(query, con))
{
try
{
con.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
url = reader.GetString(reader.GetOrdinal("Url"));
urlList.Add(url);
}
}
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
con.Close();
}
}
}
return urlList;
}
Как видите, здесь он получает соединение с БД:
using (SqlConnection con = PrjConnection.getStringConnection(dbConf.Tenant + "_PROTOCOLLO"))
Это код метода getStringConnection () (определяется всегда в одном и том же проекте DAO):
[MethodImpl(MethodImplOptions.Synchronized)]
public static SqlConnection gettringConnection(string name)
{
SqlConnectionStringBuilder bu = new SqlConnectionStringBuilder();
XmlDocument config = new XmlDocument();
config.Load(@"C:\Program Files\Information Workers Group\MyPrj\" + MyPrjSqlEngine.Properties.Resources.Progetto + @"\cfg\config.xml");
XmlNode xmlRoot = config.SelectSingleNode("connection_config");
XmlNode root = xmlRoot.SelectSingleNode("database");
string user = root.SelectSingleNode("user").InnerText;
string passwordCrypted = root.SelectSingleNode("password").InnerText;
string password = Crypto.Crypto.DecriptAes(passwordCrypted);
string server = root.SelectSingleNode("server").InnerText;
string database = name;
bu.DataSource = @server;
bu.InitialCatalog = database;
bu.IntegratedSecurity = false; // Sql Server Authentification
bu.UserID = user;
bu.Password = password;
bu.MultipleActiveResultSets = true;
SqlConnection mycon = new SqlConnection();
mycon.ConnectionString = bu.ConnectionString;
return mycon;
}
Как видно из этого метода, он извлекает и загружает XMLфайл конфигурации, который содержит информацию о соединении с базой данных, что-то вроде этого:
<connection_config>
<database>
<user>MY-USER</user>
<password>CRYPTED-PSWD</password>
<server>DB-SERVER-NAME</server>
</database>
</connection_config>
, а затем извлекает эту информацию из этого XML-файла и использует ее для создания строки соединения с БД.
Как объяснено в начале поста, он отлично работает, выполняя запрос из приложения SharePoint (я выполняю задание, и запрос выполняется, как я ожидаю, без проблем).
проблема заключается в следующем: тогда я определил новый NUnit в своем решении, чтобы протестировать методы DAO в качестве интеграционного теста, поэтому в этом тестовом проекте у меня есть этот класс:
namespace Tests
{
public class Tests
{
[SetUp]
public void Setup()
{
}
[Test]
public void Test1()
{
Assert.Pass("PASSED");
}
[Test]
public void GetIndirizzoProtocollo_XXX_YYY_ReturnSingleValue()
{
DBConnection dbConfig = new DBConnection();
dbConfig.Tenant = "XXX";
List<string> urlList = IndirizziProtocolliSQL.GetListaIndirizziSiti(dbConfig);
Assert.Pass("OK");
}
}
}
В данный моментон содержит только минималистичный метод испытаний.Как вы видите, я тестирую тот же метод DAO, который вызывается из моего задания таймера.
Отладка выполнения этого метода теста у меня:
Я правильно ввожу в IndirizziProtocolliSQL.GetListaIndirizziSiti () метод DAO.
Здесь он правильно входит в метод getStringConnection () , где начинается для правильного получения информациииз файла конфигурации XML.
Теперь переменная passwordCrypted содержит зашифрованный пароль, полученный из документа XML.Затем он пытается выполнить эту строку для расшифровки зашифрованного пароля:
string password = Crypto.Crypto.DecriptAes(passwordCrypted);
и теперь я получаю следующее исключение в трассировке стека:
Exception thrown: 'System.TypeInitializationException' in MyPrjSqlEngine.dll
An exception of type 'System.TypeInitializationException' occurred in MyPrjSqlEngine.dll but was not handled in user code
The type initializer for '<Module>' threw an exception.
Ввсплывающее окно в строке, где происходит исключение, у меня есть сообщение, подобное этому:
System.TypeInitializationException: 'The type initializer for '<Module>' threw an exception.'
EntryPointNotFoundException: A library name must be specified in a DllImport attribute applied to non-IJW methods.
Внутреннее исключение :
- InnerException {<CrtImplementationDetails>.ModuleLoadException: The C++ module failed to load.
---> System.EntryPointNotFoundException: A library name must be specified in a DllImport attribute applied to non-IJW methods.
at _getFiberPtrId()
at <CrtImplementationDetails>.LanguageSupport._Initialize(LanguageSupport* )
at <CrtImplementationDetails>.LanguageSupport.Initialize(LanguageSupport* )
--- End of inner exception stack trace ---
at <CrtImplementationDetails>.ThrowModuleLoadException(String errorMessage, Exception innerException)
at <CrtImplementationDetails>.LanguageSupport.Initialize(LanguageSupport* )
at .cctor()} System.Exception {<CrtImplementationDetails>.ModuleLoadException}
Отладка этого модульного теста у меня естьчто когда он пытается выполнить эту строку:
string password = Crypto.Crypto.DecriptAes(passwordCrypted);
я не могу сделать Step Into этот метод DecriptAes () .Я не знаю почему, потому что он входит в класс, определенный в том же проекте MyPrjSqlEngine .
Кажется, что он не может найти этот Crypto класс или что-то в этом роде.
Этот Cyrpto класс определен в том же MyPrjSqlEngine pèroject, но в другом пространстве имен:
namespace MyPrjSqlEngine.Crypto
{
public class Crypto
{
........................
........................
........................
}
}
Почему у меня возникает эта проблема при вызове из модульного теста, и у меня нет вызова непосредственно из задания таймера SharePoint?Как я могу попытаться это исправить?