Гость
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Как обойти преобразование параметров внутри выражений к int? / 4 сообщений из 4, страница 1 из 1
17.08.2012, 15:05
    #37920931
igr-z
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обойти преобразование параметров внутри выражений к int?
Столкнулся с интересной проблемой, .net все типы в выражениях ниже int приводит к int,
что очень мешает в некоторых случаях, а именно:
(Использую BL Toolkit для обращения к sql через linq, но на сколько я понял, это проблема не самой ORM, а именно linq запросов, т.к. конвертация к int закладывается в самом дереве выражений)

таблица:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
[TableName("AnyTable")]
public class AnyTableRow
{
[PrimaryKey]
public long Id;
[MapField("send_status")]
public SendStatusEnum SendStatus;
}
 
public enum SendStatusEnum : byte
{
SendNotAllowed = 1,
SendAllowed =2,
Sent = 3
}


Код: sql
1.
2.
3.
4.
CREATE TABLE [AnyTable](
[id] [bigint] NOT NULL PRIMARY KEY CLUSTERED,
[send_status] [tinyint] NOT NULL,
)


код linq запроса:
Код: c#
1.
2.
3.
4.
5.
6.
7.
_db.GetTable<AnyTableRow>()
.Where(j => j.Id < identity && j.SendStatus == SendStatusEnum.SendNotAllowed)
.Update(row =>
new Table
{
SendStatus = SendStatusEnum.SendAllowed
});


приводит к генерации sql запроса:
Код: sql
1.
2.
3.
4.
UPDATE [j]
SET [send_status] = 2
FROM [AnyTable] [j]
WHERE [j].[Id] < 123 AND Convert(Int, [j].[send_status]) = 1


он приводит поле в таблице к Int
Convert(Int, [j].[send_status]) = 1
несмотря на то, что enum имеет тип byte (enum SendStatusEnum : byte)
(при простых выборках происходит тоже самое (без update), все передаваемые параметры ниже int, подтягиваются к int)

как можно обойти такое поведение?
иначе это может сильно мешать использованию индексов в БД + лишние расходы на конвертацию
...
Рейтинг: 0 / 0
17.08.2012, 15:30
    #37920968
iConst
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обойти преобразование параметров внутри выражений к int?
igr-z ,

Дык, нет в БД данных типа byte. Чем обусловлено
Код: c#
1.
enum SendStatusEnum  : byte 

Что не сделать по-умолчанию
Код: c#
1.
2.
3.
4.
5.
6.
public enum SendStatusEnum  //int 
{
   SendNotAllowed = 1, // достаточно указать стартовое значение
   SendAllowed,
   Sent
}
...
Рейтинг: 0 / 0
19.08.2012, 12:31
    #37922047
igr-z
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обойти преобразование параметров внутри выражений к int?
Оказалось, проблема существует только с типом byte (sbyte - дает тот же результат)
аналог sbyte - tinyint, так же как у short - smallint, (но short не конвертируется)

вот пример:


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
  class Program
    {
    class Program
    {
        static void Main(string[] args)
        {
            using (var conn = new SqlConnection(@"Data Source=.;Database=Test;Integrated Security=SSPI"))
            {
                conn.Open();
                using (var db = new DbManager(conn))
                {
                    var table = db.GetTable<TableTestRow>().
                        Where(row => row.Id == 1 
                            && row.ValueInt == 1 
                            && row.ValueShort == 1 
                            && row.ValueByte == 1
                            && row.ValueEnum == StatusEnum.Status2
                            && row.ValueBit);

                    table.ToList();
                    Console.WriteLine(table.ToString());
                    Console.ReadLine();
                }
            }
        }
    }

    [TableName("TableTest")]
    public class TableTestRow
    {
        public long Id;
        public int ValueInt;
        public short ValueShort;
        public sbyte ValueByte;
        public StatusEnum ValueEnum;
        public bool ValueBit;
   }

    public enum StatusEnum : sbyte
    {
        Status1,
        Status2,
        Status3
    }




Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
CREATE TABLE [dbo].[TableTest](
                [Id] [bigint] NOT NULL PRIMARY KEY CLUSTERED,
                [ValueInt] [int] NOT NULL,
                [ValueShort] [smallint] NOT NULL,
                [ValueByte] [tinyint] NOT NULL,
                [ValueEnum] [tinyint] NOT NULL,
                [ValueBit] [bit] NOT NULL,
) 



Дает следующее:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
SELECT
        [row1].[Id],
        [row1].[ValueInt],
        [row1].[ValueShort],
        [row1].[ValueByte],
        [row1].[ValueEnum],
        [row1].[ValueBit]
FROM
        [TableTest] [row1]
WHERE
        [row1].[Id] = 1 AND
        [row1].[ValueInt] = 1 AND
        [row1].[ValueShort] = 1 AND
        Convert(Int, [row1].[ValueByte]) = 1 AND
        Convert(Int, [row1].[ValueEnum]) = 1 AND
        [row1].[ValueBit] = 1


конвертируется только byte (sbyte так же)
Кто-нибудь с этим сталкивался?

тип int для enum не подходит, таблица рассчитывается на миллиард записей, полей таких много, цена преобразования одного поля из 1 байта в 4 байта (int) будет составлять 3 Гб места на диске (только одного поля!), потому крайне важно использование индексов, которое при конвертировании полей на ходу не будет срабатывать
...
Рейтинг: 0 / 0
20.08.2012, 12:31
    #37922795
pation
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обойти преобразование параметров внутри выражений к int?
igr-zСтолкнулся с интересной проблемой, .net все типы в выражениях ниже int приводит к int

это не так
...
Рейтинг: 0 / 0
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Как обойти преобразование параметров внутри выражений к int? / 4 сообщений из 4, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]