А как можно отконвертировать Expression<Func<T>> в Expression<Func<T,T>> зная, что входной параметр во втором Expression не используется. Это нужно, что бы не писать два одинаковых выражения в InsertOrUpdate (у меня они
... [More]
здоровые). Или, по другому, как самому написать такую перегрузку для InsertOrUpdate:
public static int InsertOrUpdate<T>(
[NotNull] this Table<T> target,
[NotNull] Expression<Func<T>> insertOrUpdateSetter) [Less]
|
Решил отказаться от EditableObject... НО! Оставить EditableList<>
Чем мне это "грозит"?
Вот, от чего отказываюсь в контексте EditableObject:
1. IsDirty, Accept/Eject -Changes)
2. Автоматическая реализация INPC.
3. ???
Из-за чего всё
... [More]
это...
1. Linq2blt. Думаю, тут всё понятно. Просто жутко неудобно, а иногда и невозможно, что-то сделать. В итоге — танцы с бубном.
2. Сериализация WCF. DataContractResolver писать не получается, т.к. на этапе компиляции не известен тип BLToolkit-имплементующего класса от моего абстрактного, единсвенный вариант — в конструкторе писать что-то типа: ThisType = GetType(), и через него уже ориентироваться в методах DataContractResolver-а
3. ???
Кто, что посоветует?
Спасибо! [Less]
|
Здравствуйте!
BLT не может корректно выполнить запрос если в качестве параметров используется стандартные типы Sql (например SqlHierarhyId).
Предлагаю дополнить Sql2008DataProvider поддержкой резолвинга таких типов:
using System;
using
... [More]
System.Linq;
using Microsoft.SqlServer.Server;
namespace BLToolkit.Data.DataProvider
{
using Sql.SqlProvider;
public sealed class Sql2008DataProvider : SqlDataProviderBase
{
static System.Collections.Generic.List<Func<Type, string>> udtTypeNameResolvers;
static Sql2008DataProvider()
{
udtTypeNameResolvers = new System.Collections.Generic.List<Func<Type, string>>();
AddUdtTypeNameResolver(ResolveStandartUdt);
}
public static void AddUdtTypeNameResolver(Func<Type, string> resolver)
{
udtTypeNameResolvers.Add(resolver);
}
static string ResolveStandartUdt(Type type)
{
if (type.Namespace == "Microsoft.SqlServer.Types")
{
return type.Name.Replace("Sql", "");
}
return null;
}
public override string Name
{
get { return DataProvider.ProviderName.MsSql2008; }
}
public override ISqlProvider CreateSqlProvider()
{
return new MsSql2008SqlProvider();
}
public override void SetParameterValue(System.Data.IDbDataParameter parameter, object value)
{
base.SetParameterValue(parameter, value);
SetUdtTypeName(parameter, value);
}
private void SetUdtTypeName(System.Data.IDbDataParameter parameter, object value)
{
var sqlParameter = parameter as System.Data.SqlClient.SqlParameter;
var valueType = value.GetType();
if (sqlParameter != null)
sqlParameter.UdtTypeName = udtTypeNameResolvers.Select(_=>_(valueType)).FirstOrDefault(_=>!string.IsNullOrEmpty(_));
}
}
} [Less]
|
Здравствуйте, коллеги!
Вот, собственно, проблема с этими двумя вещами.
Есть базовая сущность. Выглядит примерно так:
[DataContract]
namespace Proj.ObjectModel
{
public abstract class BizEntity<T> : EditableObject
{
... [More]
[DataMember]
public abstract int ID { get; protected set; }
//...
}
//...
}
Есть сервис на BLT и клиенты (WinForms) на BLT. Все используют общую ObjectModel.
Сервис падает с InvalidDataContractException:
Тип "Proj.ObjectModel.BizEntity" не может быть производным от типа, который не отмечен с помощью атрибута DataContractAttribute или SerializableAttribute. Отметьте базовый тип "Proj.ObjectModel.BizEntity`1[[Proj.ObjectModel.Employee, Proj.ObjectModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]" с помощью атрибута DataContractAttribute или SerializableAttribute либо удалите их из производного типа.
Полазив по форуму понял, что когда-то это было проблемой, но потом вроде как исправили. Полез в исходники, но там то, что косается DataContractAttribute в одном месте закомментировано, а вдругом вообще не учтено. Как быть? Переделывать всё без EditableObject, EditableList<>?
Есть опасность, что чего-нить существенного лишусь (да и руками INPC делать — ).
Поделитесь опытом, пожалуйста. [Less]
|
Posted
over 12 years
ago
Здравствуйте. Суть проблемы
Expression<Func<TEntity, bool>> rule = t => (t.Id == 1 && t.Name.Contains("12"));
using (var db = new DbManager())
{
return db.GetTable<TEntity>().Where(rule).ToList();
}
... [More]
работает как надо
но если я строю Expression как
Expression<Func<KsbItso, bool>> first = t => t.Id == 1;
var invocationExpression = Expression.Invoke(t=> t.Name.Contains("12"), first.Parameters);
var resultExpr = Expression.Lambda<Func<TEntity, bool>>(Expression.AndAlso(first.Body, invocationExpression), first.Parameters);
using (var db = new DbManager())
{
return db.GetTable<TEntity>().Where(resultExpr).ToList();
}
то получаю ошибку
t.Name.Contains("12")' cannot be converted to SQL.
мб я что-то неправильно делаю, или как это исправить? [Less]
|
Можно ли в BLToolkit добавить поддержку array binding-а в каком-нибудь таком виде?
var ids = new[] { 1, 2, 3, 4 };
var names = new[] { "а", "б", "в", "г" };
var count = ids.Length;
db.SetCommand("INSERT INTO TEMP_TABLE(ID, NAME) VALUES
... [More]
(:pID, :pNAME)",
db.Parameter("pID", ids),
db.Parameter("pName", names)).ExecuteArray(count);
Провайдеры, которые это поддерживают (ODP.NET, Devart dotConnect),
выполнят команду максимально быстро, за один roundtrip к серверу.
Остальные провайдеры могут просто сделать ExecuteNonQuery столько раз, какой передан count.
PS. Поддерживается это в Oracle и Informix-e. Скорее всего еще и в Postgres-е, но тут я не уверен. [Less]
|
Привет всем
не смог найти на форуме / в доке.
нужно налету склеить некий список подзапроса в строку.
на Sql решение — "select field1 from table for xml path('')"
( аналог MySql group_concat() )
вопрос — как это сделать в лямбде?
--
... [More]
[TableName( "Users" )]
public class User
{
public Guid UserId { get; set; }
[Nullable]public string Agencies { get; set; }
}
[TableName( "Participants" )]
public class Participant
{
public Guid UserId { get; set; }
public Guid AgencyId { get; set; }
public string AgencyName { get; set; }
}
// теперь мне нужно одной командой проапдейтить у некоторых юзеров поле Agencies, кот. является строкой со списком всех агенств, с кот. у данного юзера есть связь.
db.Update<User>(
u => true/**/,
u => new User
{
// это то что нужно сделать, за исключением того, что string.Join не конвертится в Sql
Agencies = string.Join( ", ", db.GetTable<Participant>().Where( p => p.UserId ).Select( p => p.AgencyName ) )
} );
Спасибо [Less]
|
Зачем в инсерте синтаксис
_ => new MyObject()
почему для инсертов\апдейтов нельзя использовать _ => myObject
обход-то есть через экстеншн метод для IDataContext, но чисто академически интересно почему такие сложности?
|
Добрый день!
LINQ-запросы с Set+Update встраивают значения в генерируемый SQL.
К примеру, из такого запроса
var id = 123;
var newName = "NewName";
db.GetTable<Sample>()
.Where(r => r.ID == id)
.Set(r => r.Name
... [More]
, newName).Update();
генерируется такой SQL:
UPDATE Sample
SET Name = 'NewName'
WHERE ID = :id
Можно ли заставить BLToolkit генерировать в запросе параметры для SET?
Я заметил, что параметр newName генерируется, если использовать такой вариант метода Set:
.Set(r => r.Name, () => newName) // вместо константы — лямбда-выражение, которое обращается к локальной переменной
Можно ли обойтись без этой лямбды? [Less]
|
Приветствую!
Пытаюсь написать linq выражение для получения первых записей из каждой группы. Исходная таблица:
class Table1
{
public int Id { get; set; }
public int Type { get; set; }
public DateTime Created { get; set; }
}
... [More]
Хочу получить такой запрос:
select Id, Type, Created from (
select *, row_number() over (partition by Type order by Created) as rn from Table1)
where
rn = 1
Попытка №1. Использую способ, который на просторах инета рекомендуют в случае использования стандартного linq:
var result1 = from row in db.GetTable<Table1>()
group row by row.Type into grouped
select grouped.OrderBy(g=>g.Created).First();
При попутке выполнить запрос получаю ошибку:
Column 't1.Id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Генерируемый запрос:
Скрытый текст
-- MainConnection Sql MsSql2005
SELECT
[t1].[Id] as [Id1],
[t1].[Type1] as [Type11],
[t1].[Created] as [Created1],
[t1].[c1] as [c11]
FROM
[Table1] [t2]
OUTER APPLY (
SELECT TOP (1)
[keyParam].[Id],
[keyParam].[Type] as [Type1],
[keyParam].[Created],
1 as [c1]
FROM
[Table1] [keyParam]
WHERE
[t2].[Type] = [keyParam].[Type]
ORDER BY
[keyParam].[Created]
) [t1]
GROUP BY
[t2].[Type]
Попытка №2. Хочу заставить bltoolkit использовать оконную функцию
var result2 = from row in db.GetTable<Table1>()
group row by row.Type into grouped
from firstRow in grouped.OrderBy(g => g.Created).Skip(0).Take(1)
select firstRow;
Отрабатывает без ошибок, но генерит слишком сложный запрос — обрабатывает каждую группу записей поотдельности. Реальный запрос (с джоинами и более сложным условием группировки) выглядит совсем страшно.
Генерируемый запрос:
Скрытый текст
-- MainConnection Sql MsSql2005
SELECT
[t2].[Id] as [Id1],
[t2].[Type1] as [Type11],
[t2].[Created] as [Created1]
FROM
(
SELECT
[t1].[Type] as [Type2]
FROM
[Table1] [t1]
GROUP BY
[t1].[Type]
) [t3]
INNER JOIN (
SELECT *
FROM
(
SELECT
tn2.*,
ROW_NUMBER() OVER
(
ORDER BY
obyn2
) as rnn2
FROM
(
SELECT
[keyParam].[Id],
[keyParam].[Type] as [Type1],
[keyParam].[Created],
[keyParam].[Created] as [obyn2]
FROM
[Table1] [keyParam]
) tn2
) tn21
WHERE
tn21.rnn2 = 1
) [t2] ON [t3].[Type2] = [t2].[Type1]
Попытка №3. Вызов row_number() с помощью функции расширения.
Функция расширения:
[SqlExpression("row_number() over (partition by [Type] order by [Created] desc)", ServerSideOnly = true)]
public static long RowNumber()
{
throw new NotImplementedException();
}
Запрос на linq:
var result3 = from rowNumbered in
(
from row in db.GetTable<Table1>()
select new { row, row_number = RowNumber() })
where rowNumbered.row_number == 1
select rowNumbered.row;
Отрабатывает с ошибкой:
"Windowed functions can only appear in the SELECT or ORDER BY clauses."
Генерируемый запрос:
Скрытый текст
-- MainConnection Sql MsSql2005
SELECT
[row1].[Id],
[row1].[Type] as [Type1],
[row1].[Created]
FROM
[Table1] [row1]
WHERE
row_number() over (partition by [Type] order by [Created] desc) = 1
Если протащить генерируемое поле row_number до клиента, то запрос отрабатывает без ошибок и генерируется ожидаемый sql запрос. Но протаскивать левое поле не хочется — придется замусоривать лишними полями классы — модели клиента.
Если ли другой способ достижения результата? [Less]
|