Вопрос — subj.
Пример, чего хочется:
var key1 = "key1";
using (var dbSession = new DbManager())
{
var ret = dbSession.SetCommand("select top 1 Pvalue from _test where Pname=@pname",
... [More]
dbSession.Parameter("@pname", key1, System.Data.DbType.AnsiString, 24)).ExecuteScalar<string>();
} Конвертирует запрос в:
exec sp_executesql N'select top 1 Pvalue from _test where Pname=@pname',N'@pname varchar(24)',@pname='key1' отлично!
А вот с LINQ-ом:
[TableName("_test")]
public class TestRec
{
...
[DbType(System.Data.DbType.AnsiString, 24)]
public string Pname { get; set; }
[DbType(System.Data.DbType.AnsiString, 48)]
public string Pvalue { get; set; }
...
}
var key1 = "key1";
using (var dbSession = new DbManager())
{
var ret = (from item in dbSession.GetTable<TestRec>()
where item.Pname == key1
select item.Pvalue).FirstOrDefault();
} получаем на выходе:
exec sp_executesql N'SELECT TOP (1)
[item].[Pvalue]
FROM
[_test] [item]
WHERE
[item].[Pname] = @key1
',N'@key1 nvarchar(4)',@key1=N'key1' при том что тип колонки Pname явно задан.
Как или где, можно ли явно указать тип параметра key1 в LINQ запросе?
В идеале, может ли BLT сам по умолчанию указывать тип key1 используя тип левого операнда (Pname)?
Несоответствие типов влияет на производительность выборки, хочется ето исправить если возможно.
Спасибо [Less]
|
Здравствуйте, IT!
Недавно наткнулся на сервис http://www.symbolsource.org, который позволяет размещать символы и исходники для пакетов NuGet. Предлагаю Вам разместить на данном сервере исходники и символы для BLT.
|
Здравствуйте, IT!
Недавно наткнулся на сервис http://www.symbolsource.org, который позволяет размещать символы и исходники для пакетов NuGet. Предлагаю Вам разместить на данном сервере исходники и символы для BLT.
|
На примере из http://rsdn.ru/projects/rfd/linq/LinqWithBLToolkit.xml
using (var db = new NorthwindDB())
{
var query = db.Employee;
foreach (var employee in query)
{
Console.WriteLine("{0} {1}"
... [More]
, employee.EmployeeID, employee.FirstName);
// Если мне на очередной записи не понравилось employee.FirstName
// могу я его изменить и обновить эту запись в БД?
}
}
ну и собственно как?
з.ы. составить запрос на обновление видимо не судьба, т.к. в реале в записи лежит двоичный дамп, который надо расковыривать и менять пару байт, если они неправильные. [Less]
|
На примере из http://rsdn.ru/projects/rfd/linq/LinqWithBLToolkit.xml
using (var db = new NorthwindDB())
{
var query = db.Employee;
foreach (var employee in query)
{
Console.WriteLine("{0} {1}"
... [More]
, employee.EmployeeID, employee.FirstName);
// Если мне на очередной записи не понравилось employee.FirstName
// могу я его изменить и обновить эту запись в БД?
}
}
ну и собственно как?
з.ы. составить запрос на обновление видимо не судьба, т.к. в реале в записи лежит двоичный дамп, который надо расковыривать и менять пару байт, если они неправильные. [Less]
|
SqlServer 2008R2:
Таблица:
create table test
(
id int not null,
data image null
)
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using BLToolkit.Data;
using
... [More]
BLToolkit.DataAccess;
using BLToolkit.EditableObjects;
using BLToolkit.Reflection;
using BLToolkit.Mapping;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string connString =
"Data Source=dbserver\\sql2008;" +
"User Id=sa;" +
"Password=sa;" +
"Initial Catalog=DataDb;";
DbManager.AddConnectionString("Sql.", connString);
DbManager.DefaultConfiguration = "Sql.";
var item = new Test();
item.Id = 1;
item.Data = null;
var query = new SqlQuery<Test>();
using (var db = new DbManager())
{
query.Update(db, item);
}
}
}
[TableName("test")]
public class Test
{
[MapField("id"), PrimaryKey] public int Id;
[MapField("data")] public byte[] Data;
}
}
Ожидается, что если в 'Data' будет 'null', то тип параметра в запросе должен быть 'image' вместо 'nvarchar(4000)', так как в текущей версии запрос падает с ошибкой: Operand type clash: nvarchar is incompatible with image
exec sp_executesql N'UPDATE
[test]
SET
[data] = @data_P
WHERE
[id] = @id_W',N'@data_P nvarchar(4000),@id_W int',@data_P=NULL,@id_W=1
20.08.12 13:24: Перенесено модератором из 'Nemerle' — WolfHound [Less]
|
SqlServer 2008R2:
Таблица:
create table test
(
id int not null,
data image null
)
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using BLToolkit.Data;
using
... [More]
BLToolkit.DataAccess;
using BLToolkit.EditableObjects;
using BLToolkit.Reflection;
using BLToolkit.Mapping;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string connString =
"Data Source=dbserver\\sql2008;" +
"User Id=sa;" +
"Password=sa;" +
"Initial Catalog=DataDb;";
DbManager.AddConnectionString("Sql.", connString);
DbManager.DefaultConfiguration = "Sql.";
var item = new Test();
item.Id = 1;
item.Data = null;
var query = new SqlQuery<Test>();
using (var db = new DbManager())
{
query.Update(db, item);
}
}
}
[TableName("test")]
public class Test
{
[MapField("id"), PrimaryKey] public int Id;
[MapField("data")] public byte[] Data;
}
}
Ожидается, что если в 'Data' будет 'null', то тип параметра в запросе должен быть 'image' вместо 'nvarchar(4000)', так как в текущей версии запрос падает с ошибкой: Operand type clash: nvarchar is incompatible with image
exec sp_executesql N'UPDATE
[test]
SET
[data] = @data_P
WHERE
[id] = @id_W',N'@data_P nvarchar(4000),@id_W int',@data_P=NULL,@id_W=1
20.08.12 13:24: Перенесено модератором из 'Nemerle' — WolfHound [Less]
|
При использовании маппера последний(из репозитория) BLToolkit:
(.net 4, но есть и 4.5)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BLToolkit.EditableObjects;
... [More]
using BLToolkit.Reflection;
using BLToolkit.Mapping;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Test test = TypeAccessor<Test>.CreateInstance();
var mapper = Map.GetObjectMapper<Test, Test>();
var testCopy = mapper(test);
}
}
public abstract class Test
{
public abstract int Id { get; set; }
}
}... << RSDN@Home 1.2.0 alpha 5 rev. 66>> [Less]
|
При использовании маппера последний(из репозитория) BLToolkit:
(.net 4, но есть и 4.5)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BLToolkit.EditableObjects;
... [More]
using BLToolkit.Reflection;
using BLToolkit.Mapping;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Test test = TypeAccessor<Test>.CreateInstance();
var mapper = Map.GetObjectMapper<Test, Test>();
var testCopy = mapper(test);
}
}
public abstract class Test
{
public abstract int Id { get; set; }
}
}... << RSDN@Home 1.2.0 alpha 5 rev. 66>> [Less]
|
1) Проблема в том, что когда manual_weight == null, то получается пустая запись, в режиме отладки при перечислении результатов получается:
Message = "Function Average returns non-nullable value, but result is NULL. Use nullable version of the
... [More]
function instead."
Source = "BLToolkit.4"
at BLToolkit.Data.Linq.Builder.AggregationBuilder.AggregationContext.CheckNullValue(Object value, Object context)
at lambda_method(Closure , QueryContext , IDataContext , IDataReader , Expression , Object[] )
at BLToolkit.Data.Linq.Query`1.<Map>d__60.MoveNext()
at System.Linq.SystemCore_EnumerableDebugView`1.get_Items()
Запрос:
(from _ in serverContext.Wagons
where _.id_train == id
select new
{
Id = _.id,
Nom = _.WagonType.type ? _.nom_in_train.ToString(CultureInfo.InvariantCulture) : "Л" + _.nom_in_train.ToString(CultureInfo.InvariantCulture),
WagonType = _.WagonType.name,
Axles = _.manual_weight == null ? _.WagonType.axis : _.Axles.Count(),
Weight = _.manual_weight == null ? _.manual_weight : _.Axles.Sum(a => a.weight_left_whell + a.weight_right_whell) / 1000,
Speed = _.manual_weight == null ? null : (float?)_.Axles.Average(a => a.speed)
});
По аналогии с условием _.WagonType.type, я ожидал что в SQL это преобразуется как (case when ... then ... else ...end) as Result, но получилось вообще нечто странное...
SqlText=
-- MsSql2008
-- DECLARE @id1 Int32
-- SET @id1 = 2
SELECT
[_].[id],
[t1].[type] as [type1],
[_].[nom_in_train],
[t1].[name],
[_].[manual_weight],
[t1].[axis],
(
SELECT
Count(*)
FROM
[Axles] [c]
WHERE
[_].[id] = [c].[id_wagon]
) as [c1],
(
SELECT
Sum([c3].[weight_left_whell] + [c3].[weight_right_whell])
FROM
[Axles] [c3]
WHERE
[_].[id] = [c3].[id_wagon]
) as [c4],
(
SELECT
Avg([c6].[speed])
FROM
[Axles] [c6]
WHERE
[_].[id] = [c6].[id_wagon]
) as [c7]
FROM
[Wagons] [_]
INNER JOIN [WagonType] [t1] ON [_].[id_wagontype] = [t1].[id]
WHERE
[_].[id_train] = @id1
Ну решение проблемы пока такое:
CREATE VIEW dbo.Wagons_J (
Id,
Nom,
WagonType,
Axles,
Weight,
Speed
)
AS
SELECT
w.id as Id,
(
case when wt.[type] = 1 then
Convert(nvarchar, w.nom_in_train)
else
'Л' + Convert(nvarchar, w.nom_in_train)
end
) as [Nom],
wt.[name] as [WagonType],
(
case when w.manual_weight is null then
(select count(*) from Axles a where a.id_wagon = w.id)
else
wt.axis
end
) as [Axles],
(
case when w.manual_weight is null then
(select sum(a.weight_left_whell + a.weight_right_whell) from Axles a where a.id_wagon = w.id)
else
w.manual_weight
end
) as [Weight],
(
case when w.manual_weight is null then
(select avg(a.speed) from Axles a where a.id_wagon = w.id)
else
NULL
end
) as [Speed]
FROM
Wagons w
INNER JOIN
WagonType wt on w.id_wagontype = wt.id
2) генерируется код, который не выполняется
from _ in serverContext.Trains select _.Wagons.Where(w => w.WagonType.type).Sum(w => w.manual_weight == null ? w.manual_weight : w.Axles.Sum(a => a.weight_left_whell + a.weight_right_whell))/1000;
-- MsSql2008
SELECT
(
SELECT
Sum(CASE
WHEN [c3].[manual_weight] IS NULL
THEN [c3].[manual_weight]
ELSE (
SELECT
Sum([c].[weight_left_whell] + [c].[weight_right_whell])
FROM
[Axles] [c]
WHERE
[c3].[id] = [c].[id_wagon]
)
END)
FROM
[Wagons] [c3]
INNER JOIN [WagonType] [t1] ON [c3].[id_wagontype] = [t1].[id]
WHERE
[_].[id] = [c3].[id_train] AND [t1].[type] = 1
) as [c4]
FROM
[Trains] [_]
{"Невозможно выполнить агрегатную функцию для выражения, содержащего выражение или вложенный запрос."}
at BLToolkit.Data.DbManager.OnOperationException(OperationType op, DataException ex)
at BLToolkit.Data.DbManager.HandleOperationException(OperationType op, Exception ex)
at BLToolkit.Data.DbManager.ExecuteOperation[T](OperationType operationType, Func`1 operation)
at BLToolkit.Data.DbManager.ExecuteReaderInternal(CommandBehavior commandBehavior)
at BLToolkit.Data.DbManager.ExecuteReader(CommandBehavior commandBehavior)
at BLToolkit.Data.DbManager.ExecuteReaderInternal()
at BLToolkit.Data.DbManager.ExecuteReader()
at BLToolkit.Data.DbManager.BLToolkit.Data.Linq.IDataContext.ExecuteReader(Object query)
at BLToolkit.Data.Linq.Query`1.<RunQuery>d__11.MoveNext()
at BLToolkit.Data.Linq.Query`1.<Map>d__60.MoveNext()
at System.Linq.SystemCore_EnumerableDebugView`1.get_Items()
собственно в sql management studio такой запрос не выполняется с таким же сообщением.
тут пока нет решения, но есть немного похожая штука:
from _ in serverContext.Trains
select _.id_weight_calculate_type == 1 || _.id_weight_calculate_type == null ?
_.Wagons.Where(w => w.WagonType.type && w.manual_weight == null).Sum(w => w.Axles.Sum(a => a.weight_left_whell + a.weight_right_whell)) / 1000 :
_.Wagons.Where(w => w.WagonType.type && w.manual_weight != null).Sum(w => w.manual_weight) / 1000;
Пришлось сделать флаг _.id_weight_calculate_type, но появилось ограничение, что manual_weight должно быть одинаково != null или == null для одного и того же Train.
Да и то не генерируется case в sql, но хотя бы работает в отличие от вышеописанной штуки:
-- MsSql2008
SELECT
[_].[id_weight_calculate_type],
(
SELECT
Sum([t2].[c1])
FROM
[Wagons] [c3]
INNER JOIN [WagonType] [t1] ON [c3].[id_wagontype] = [t1].[id]
OUTER APPLY (
SELECT
Sum([c].[weight_left_whell] + [c].[weight_right_whell]) as [c1]
FROM
[Axles] [c]
WHERE
[c3].[id] = [c].[id_wagon]
) [t2]
WHERE
[_].[id] = [c3].[id_train] AND [t1].[type] = 1 AND
[c3].[manual_weight] IS NULL
) as [c4],
(
SELECT
Sum([c6].[manual_weight])
FROM
[Wagons] [c6]
INNER JOIN [WagonType] [t3] ON [c6].[id_wagontype] = [t3].[id]
WHERE
[_].[id] = [c6].[id_train] AND [t3].[type] = 1 AND
[c6].[manual_weight] IS NOT NULL
) as [c7]
FROM
[Trains] [_]
P.S.: Как там дела с здесь?
тут пока мысль тоже сделать View с функцией sql.
P.P.S: во как много текста написал ) [Less]
|