Я просто подумал, что добавлю, как я решил это.
Я создал пару вспомогательных классов, которые имитируют поведение Linq to Entities, и использую их в своих специальных хранимых процедурах. Он далек от совершенства или даже хорош, но в результате код выглядит очень похожим на Linq to Entities. Это важно для меня, так как остальная часть моего уровня базы данных будет использовать Linq to Entities.
В идеальном мире я мог бы сформулировать запрос к Linq to Entities, а затем использовать результат, несколько похожий на то, что я делаю сейчас.
Вот и мы ...
Код используется следующим образом:
var connectionString = new SqlConnectionStringBuilder
{
DataSource = @"C:\Temp\Northwind.mdf"
};
var commandText = "select * from Customers";
using (var rows = new SqlCommandHelper(connectionString.ToString(), System.Data.CommandType.Text, commandText))
{
foreach (dynamic row in rows)
{
try
{
Console.WriteLine(row.Fax ?? "Emtpy");
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Invalid column name");
}
}
}
Как видите, перечисление строк выглядит примерно так, как если бы я использовал Linq to Entities вместо SqlCommandHelper
.
Класс SqlCommandHelper
представляет собой следующий код:
class SqlCommandHelper : IEnumerable<DynamicSqlRow>, IDisposable
{
private SqlConnection connection;
private SqlCommand command;
public SqlCommandHelper(string connectionString, System.Data.CommandType commandType, string commandText, params SqlParameter[] parameters)
{
connection = new SqlConnection(connectionString);
command = new SqlCommand
{
CommandText = commandText,
CommandType = commandType,
Connection = connection
};
command.Parameters.AddRange(parameters);
}
public IEnumerator<DynamicSqlRow> GetEnumerator()
{
if (connection.State != System.Data.ConnectionState.Open)
{
connection.Open();
}
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
yield return new DynamicSqlRow(reader);
}
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Dispose()
{
command.Dispose();
connection.Dispose();
}
}
Как видите, магия находится внутри DynamicSqlRow
. Хочу отметить, что для компиляции вам нужно импортировать пространство имен System.Dynamic
для DynamicSqlRow
.
class DynamicSqlRow : DynamicObject
{
System.Data.IDataReader reader;
public DynamicSqlRow(System.Data.IDataReader reader)
{
this.reader = reader;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var row = reader[binder.Name];
result = row is DBNull ? null : row;
return true;
}
}
Я надеюсь, что этот код может быть полезен кому-то еще или что он заставит кого-то придумать лучшее решение.
Полезной ссылкой для меня была Пошаговое руководство. Создание и использование динамических объектов из MSDN.
Берегите себя