templated InsertWithIdentity
От: Holms США  
Дата: 15.02.10 20:44
Оценка:
привет

Можно ли добавить overload для InsertWithIdentity такого вида

T InsertWithIdentity<T>()

а то приходится всегда кастить из object в нужный тип, в 99% случаем это Convert.ToInt32

Спасибо
... << RSDN@Home 1.2.0 alpha 4 rev. 1441>>
The life is relative and reversible.
Re: templated InsertWithIdentity
От: IT Россия linq2db.com
Дата: 15.02.10 21:03
Оценка:
Здравствуйте, Holms, Вы писали:

H>Можно ли добавить overload для InsertWithIdentity такого вида


H>T InsertWithIdentity<T>()


К сожалению, такое сделать нельзя из-за ограничений C#. Сигнатура метода InsertWithIdentity уже включает обобщенные параметры:

public static object InsertWithIdentity<T>([NotNull] this IValueInsertable<T> source)
public static object InsertWithIdentity<T>([NotNull] this Table<T> target, [NotNull] Expression<Func<T>> setter)
public static object InsertWithIdentity<TSource,TTarget>(
public static object InsertWithIdentity<TSource,TTarget>([NotNull] this ISelectInsertable<TSource,TTarget> source)

Добавление ещё одного параметра заставит явно указывать их все, т.к. в C# нельзя указывать неполный список обобщённых параметров.
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: templated InsertWithIdentity
От: Holms США  
Дата: 15.02.10 21:11
Оценка:
Здравствуйте, IT, Вы писали:

IT>К сожалению, такое сделать нельзя из-за ограничений C#. Сигнатура метода InsertWithIdentity уже включает обобщенные параметры:


IT>
IT>public static object InsertWithIdentity<T>([NotNull] this IValueInsertable<T> source)
IT>public static object InsertWithIdentity<T>([NotNull] this Table<T> target, [NotNull] Expression<Func<T>> setter)
IT>public static object InsertWithIdentity<TSource,TTarget>(
IT>public static object InsertWithIdentity<TSource,TTarget>([NotNull] this ISelectInsertable<TSource,TTarget> source)
IT>

IT>Добавление ещё одного параметра заставит явно указывать их все, т.к. в C# нельзя указывать неполный список обобщённых параметров.

ладно с этим можно прожить, а как насчет такого метода InsertOrUpdate
а то уже устал писать такой код

int rows =
        ctx.ProjectFinance
            .Where(_ => _.ProjectId == projectId && _.PhaseName == phaseName)
            .Set(_ => _.OriginalBudget, budgetOriginal)
            .Set(_ => _.CurrentBudget, budgetCurrent)
            .Update();
    if (rows == 0)
        ctx.ProjectFinance
            .Insert(() => new ProjectFinance
                                            {
                                                ProjectId = projectId,
                                                PhaseName = phaseName,
                                                OriginalBudget = budgetOriginal,
                                                CurrentBudget = budgetCurrent
                                            });
... << RSDN@Home 1.2.0 alpha 4 rev. 1441>>
The life is relative and reversible.
Re[3]: templated InsertWithIdentity
От: IT Россия linq2db.com
Дата: 15.02.10 21:40
Оценка: :))
Здравствуйте, Holms, Вы писали:

H>ладно с этим можно прожить, а как насчет такого метода InsertOrUpdate

H>а то уже устал писать такой код

Upsert?

Давайте подумаем как это лучше сделать. Я знаю, что MSSQL 2008 и DB2 поддерживают MERGE и там это можно сделать без проблем. А как быть с другими провайдерами? Какой код генерировать?
Если нам не помогут, то мы тоже никого не пощадим.
Re[4]: templated InsertWithIdentity
От: Holms США  
Дата: 15.02.10 21:49
Оценка:
Здравствуйте, IT, Вы писали:


IT>Upsert?



IT>Давайте подумаем как это лучше сделать. Я знаю, что MSSQL 2008 и DB2 поддерживают MERGE и там это можно сделать без проблем. А как быть с другими провайдерами? Какой код генерировать?

Я бы генерировал для всех тот-же код как и у меня в вопросе. т.е. пытаемся делать Update если ничего небыло делаем Insert.

а синтаксис будет как для Update

ctx.ProjectFinance
    .Where(_ => _.ProjectId == projectId && _.PhaseName == phaseName)
    .Set(_ => _.OriginalBudget, budgetOriginal)
    .Set(_ => _.CurrentBudget, budgetCurrent)
    .SetI(_ => _.PhaseName, phaseName) //
    .Upsert();



SetI или что-то другое надо, так как для Insert-a возможно будет надо добавить больше значений.
... << RSDN@Home 1.2.0 alpha 4 rev. 1441>>
The life is relative and reversible.
Re[4]: templated InsertWithIdentity
От: Блудов Павел Россия  
Дата: 16.02.10 03:38
Оценка:
Здравствуйте, IT, Вы писали:

IT>Upsert?

Обычно его называют Merge.
Re[5]: templated InsertWithIdentity
От: IT Россия linq2db.com
Дата: 16.02.10 04:00
Оценка:
Здравствуйте, Блудов Павел, Вы писали:

IT>>Upsert?

БП>Обычно его называют Merge.

Merge помощнее будет, чем Upsert.
Если нам не помогут, то мы тоже никого не пощадим.
Re: templated InsertWithIdentity
От: IT Россия linq2db.com
Дата: 24.02.10 04:56
Оценка:
Здравствуйте, Holms, Вы писали:

H>Можно ли добавить overload для InsertWithIdentity такого вида

H>T InsertWithIdentity<T>()

Done.
Если нам не помогут, то мы тоже никого не пощадим.
Re[4]: templated InsertWithIdentity
От: MozgC США http://nightcoder.livejournal.com
Дата: 24.03.11 17:43
Оценка:
Здравствуйте, IT, Вы писали:

IT>Давайте подумаем как это лучше сделать. Я знаю, что MSSQL 2008 и DB2 поддерживают MERGE и там это можно сделать без проблем. А как быть с другими провайдерами? Какой код генерировать?


В MySql:

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;

INSERT ... ON DUPLICATE KEY UPDATE Syntax
Re[5]: templated InsertWithIdentity
От: IT Россия linq2db.com
Дата: 24.03.11 18:50
Оценка:
Здравствуйте, MozgC, Вы писали:

IT>>Давайте подумаем как это лучше сделать. Я знаю, что MSSQL 2008 и DB2 поддерживают MERGE и там это можно сделать без проблем. А как быть с другими провайдерами? Какой код генерировать?


MC>В MySql:


MC>
INSERT INTO table (a,b,c) VALUES (1,2,3)
MC>  ON DUPLICATE KEY UPDATE c=c+1;

MC>INSERT ... ON DUPLICATE KEY UPDATE Syntax

Тогда этот код надо ещё как-то уметь возвращать.
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: templated InsertWithIdentity
От: MozgC США http://nightcoder.livejournal.com
Дата: 24.03.11 19:15
Оценка:
Здравствуйте, IT, Вы писали:

IT>Тогда этот код надо ещё как-то уметь возвращать.


Пример нехороший, вот я как-то так это вижу:

[TableName(Name="custpercents")]
public partial class Custpercent
{
    [Identity, PrimaryKey(1)] public int      ID         { get; set; } // int(10)
                              public int      CustomerID { get; set; } // int(10)
                              public int      SupplierID { get; set; } // int(10)
                              public int      Perc       { get; set; } // int(10)
                              public DateTime TS         { get; set; } // timestamp
}


db.UpdateOrInsert(custpercent); // need also support UpdateOrInsertWithIdentity()

генерирует SQL (mysql):

INSERT INTO custpercets 
(CustomerID, SupplierID, Perc, TS) 
VALUES
(75, 15, 10, '2011-03-24 22:07:20')
ON DUPLICATE KEY UPDATE 
CustomerID = 75, SupplierID = 15, Perc = 10, TS = '2011-03-24 22:07:20'


В моем случае на CustomerID & SupplierID стоит составной уникальный индекс, поэтому в части ON DUPLICATE KEY UPDATE их можно было бы не писать, но думаю это будет слишком заморочно для BLT, так что пусть повторяются.

Второй пример (когда нет полного объекта):

db.Custpercents.InsertOrUpdate(
  () => new Custpercent
    {
      CustomerID = 75,
      SupplierID = 15,
      Perc = 10
    });

SQL:

INSERT INTO custpercets 
(CustomerID, SupplierID, Perc) 
VALUES
(75, 15, 10)
ON DUPLICATE KEY UPDATE 
CustomerID = 75, SupplierID = 15, Perc = 10

Думаю что как-то так, может что-то не учел..

  Для сравнения, вот как приходится делать сейчас
using (var db = new DataModel())
{
    int rowsUpdated = db.Custpercents
        .Where(cp => cp.CustomerID == customerID && cp.SupplierID == supplierID)
        .Update(cp => new Custpercent {Perc = profitPercent});

    if (rowsUpdated == 0)
    {
        db.Custpercents.Insert(() => new Custpercent
            {
                CustomerID = customerID,
                SupplierID = supplierID,
                Perc = profitPercent
            });
    }
}
Re[7]: templated InsertWithIdentity
От: MozgC США http://nightcoder.livejournal.com
Дата: 24.03.11 19:29
Оценка:
По поводу востребованности данной фичи — у меня на реальном проекте ON DUPLICATE KEY UPDATE встречается в 4-5% запросов, т.е. относительно часто.
К тому же оно избавляет от лишнего round-tripа на сервер.
Re[4]: templated InsertWithIdentity
От: MozgC США http://nightcoder.livejournal.com
Дата: 15.06.11 19:01
Оценка:
Здравствуйте, IT, Вы писали:

IT>Давайте подумаем как это лучше сделать. Я знаю, что MSSQL 2008 и DB2 поддерживают MERGE и там это можно сделать без проблем. А как быть с другими провайдерами? Какой код генерировать?


Игорь, сорри за назойливость, но есть ли надежда что будет поддержка Merge? А то прямо грустно писать двухэтажные запросы с 2 раундтрипами на сервер (особенно когда двухзвенка). Причем желательно делать чтобы было именно одним запросом, чтобы не было лишних раундтрипов — насколько я понимаю во всех основных БД это поддерживается (в SQL Server и Oracle — Merge, в MySql — ON DUPLICATE KEY UPDATE), к тому же если не делать одним запросом то можно нарваться на race condition. Чуть выше я писал как я это вижу на примере MySql.
Re[5]: templated InsertWithIdentity
От: IT Россия linq2db.com
Дата: 15.06.11 19:29
Оценка:
Здравствуйте, MozgC, Вы писали:

MC>Игорь, сорри за назойливость, но есть ли надежда что будет поддержка Merge?


Надеюсь в течении недели закончить с новым парсером (там только наследование осталось) и тогда можно будет заняться новыми фичами.
Если нам не помогут, то мы тоже никого не пощадим.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.