- Хроники. - -
LINQ Insert or Update еще одно решение.
Posted By Ikutsin On 4 февраля 2009 @ 9:52 In .NET C#,MSSQL | Comments Disabled
В одной из моих прошлых записей [1] я рассказывал, что 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);
}
Спасибо Владимиру Калошину за код.
Article printed from Хроники.:
URL to article: /791-linq-insert-or-update-eshhe-odno-reshenie
URLs in this post:
[1] прошлых записей: /157-metod-saveorupdate-dlya-linq-to-sql
Click here to print.
Copyright © 2008 Все, что меня окружает. All rights reserved.