понедельник, 16 декабря 2013 г.

Error: Unknown Return Type, The return types for the following stored procedures could not be detected

During our last project we decided to use Linq to SQL context for object mapping as we needed to use only few stored procedures from MSSQL database.
But when I tried to map required procedures I'd got an error: Error: Unknown Return Type, The return types for the following stored procedures could not be detected. 
At glance research I found following articles according the issue: Unknow return type errorHow to get multiple result set of procedure using LINQ to SQL.
I knew exactly that there weren't declared any temporary tables in these stored procedures. But I wasn't quite sure about multiply results. In fact, it were very big stored procedures, about 2000 rows in each,  moreover I didn't write the SPs by myself, so it was T-SQL encapsulation in action :). As a result of this I decided to find out how Linq to SQL gets metadata information about SP result fields. Via Mr. Google I found following: Getting Return Metadata from Stored Procedures
I tried it and you can see what I've got:

But it wasn't last problem, during the query's execution I got this nice message:
After a few seconds I found out that the problem comes from external CLR library that our database  actually use. As a matter of fact there was a following scenario: when the Linq to SQL tried to get stored procedure metadata it called all sp's inner  functions and procedures and as you can see from the picture above when FMTONLY mode set some arguments to the CLR function "RegexGetMatchGroupValue" it returns exception.
When I fixed multiply results set and this error in CLR everything had started to work perfectly.
So the main idea is: if you have got error when you're adding stored procedure to Linq to Sql data context. Firstly, try it with FMTONLY mode. It will show you all errors that can be reason of the headache.

четверг, 18 апреля 2013 г.

Visual Studio project AfterBuilt event

Если вдруг вы используете два .exe приложения в решении Visual Studio где один проект ссылается на другой (т.е. использует его открытые классы) то может возникнуть проблема с компиляцией конфигурационного файла того проекта на который вы ссылаетесь.
Например:
Есть проект Master, расположен в С:\MasterAndSlave\Master
Есть проект Slave, расположен в C:\MasterAndSlave\Slave

Оба они расположены в одном решении MasterAndSlave при этом Master ссылается на Slave

У проекта Slave есть конфигурационный файл App.config который содержит нужные Slave параметры для работы. 
При компиляции проекта Master в его bin\[Имя конфигурации] директории мы получим список файлов:
  • Master.exe - исполняемый файл основного проекта
  • Master.vshost.exe - файл для работы в режиме Debug (если не выбрана конфигурация Release)
  • Master.exe.config - конфигурационный файл Master-а
  • Slave.exe - исполняемый файл Slave
  • Slave.exe.config - конфигурационный файл Slave-а
На первый взгляд все нормально, но если по каким либо причинам вам понадобиться изменить App.config в Slave проекте, то возникнут проблемы. А именно скомпилированный для Master файл Slave.exe.config останется без каких либо изменений, что может конкретно осложнить вам жизненный путь к успеху :).

Решается проблема не очень сложно, нужно добавить к событию AfterBuild копирование нужно нам файла конфига.
Отрываете файл проекта Master.csproj/vbproj в любом текстовом редакторе и добавляете следующие изменения:

<Target Name="AfterBuild">
    <Copy SourceFiles="$(ProjectDir)\[Slave_Folder]\bin\$(Configuration)\[Slave_exe_file_name].exe.config" 
          DestinationFolder="$(TargetDir)" />
  </Target>

Что для вышеописанного примера выглядит так:

<Target Name="AfterBuild">
    <Copy SourceFiles="$(ProjectDir)\Slave\bin\$(Configuration)\Slave.exe.config" 
          DestinationFolder="$(TargetDir)" />
  </Target>