В одной из моих прошлых записей я рассказывал, что LINQ не совсем белый и пушистый, а иногда даже сильно ругается. Речь шла о методе SaveOrUpdate, сейчас я продолжу тему.
Прошлый пример похож на то, что по сути должен делать сам LINQ to MS SQL провайдер, естественно с кучей дополнительных деталей, на которых по всей видимости, часто возникают проблемы. Недостаток такого решения в том, что из него сложно сделать универсальный метод, так как неизбежно нужно сделать предварительную выборку по какому-либо ключу.
var originalEntity = dc.GetTable().Where(x => x.id== newEntity.id).SingleOrDefault();
Помочь может интерфейс. В таком случае, имя первичного ключа должно быть одинаковым.
Один мой коллега, надеюсь уже друг, разрешил опубликовать на блоге его реализацию расширения на class Table. Этот подход не требует никаких интерфейсов, а делает выборку с помощью простого SQL запроса. Никаких блужданий по деревьям выражений, или исправлений провайдера, жестко и эффективно. Вот код метода:
public static void InsertOrUpdateOnSubmit(this Table table, T entity)
where T : class
{
Dictionary primaryKeys = new Dictionary();
foreach (var property in entity.GetType().GetProperties())
foreach (ColumnAttribute ca in property.GetCustomAttributes(typeof(ColumnAttribute), false))
if (ca.IsPrimaryKey)
primaryKeys.Add(property.Name, property.GetValue(entity, null));
string tableName;
object[] tempAttributes = entity.GetType().GetCustomAttributes(typeof(TableAttribute), true);
if (tempAttributes.Length > 0)
tableName = (tempAttributes[0] as TableAttribute).Name;
else
throw new ArgumentException("Entity is not mapped to table");
string command = "SELECT * FROM " + tableName + " WHERE ";
int count = 0;
bool first = true;
foreach (var primaryKey in primaryKeys)
{
if (!first) command += " AND "; else first = false;
command += primaryKey.Key + " = {" + count++ + "}";
}
var originalEntity = table.Context.ExecuteQuery(command, primaryKeys.Values.ToArray()).SingleOrDefault();
if (originalEntity != null)
foreach (var property in entity.GetType().GetProperties())
{
PropertyInfo orignProperty = originalEntity.GetType().GetProperty(property.Name);
orignProperty.SetValue(originalEntity, property.GetValue(entity, null), null);
}
else
table.InsertOnSubmit(entity);
}
Спасибо Владимиру Калошину за код.
Метки:ASP.NET, C#, база данных
Похожие статьи
- 15 октября 2008 -- Метод SaveOrUpdate для Linq to SQL. (3)
- 31 августа 2009 -- CRUD на SQLite (5)
- 1 июля 2008 -- Создание INSERT скрипта для данных таблицы MSSQL. (5)
- 19 сентября 2010 -- StringTemplate на C# (Часть 3) (0)
- 11 декабря 2008 -- Генерация Entity классов с помощью MSSQL. (3)
6 августа, 2013 at 9:56
Спасибо конечно, но а таком виде пример совершенно не читабелен,пойду искать дальше
16 августа, 2013 at 17:51
А скопировать в удобный для себя редактор религия не позволяет?