- Хроники. - -

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

Copyright © 2008 Все, что меня окружает. All rights reserved.