Как указать точность DateTimeOffset с Linq-to-Sql

У меня есть проект VS2010 с классами Linq-to-SQL, сгенерированными из базы данных SQL 2008. Соответствующая таблица имеет специальный столбец Created, этот столбец имеет тип datetimeoffset(3) и используется в качестве ключа разделения ежедневно:

CREATE TABLE [dbo].[tableA](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Created] [datetimeoffset](3) NOT NULL,
    [A] [int] NULL,
 CONSTRAINT [PK_TableA] PRIMARY KEY CLUSTERED 
(
    [Created] ASC,
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) on partScheme_Daily_OnCreatedDate (Created)
) on partScheme_Daily_OnCreatedDate (Created)

Сгенерированный код linq-to-SQL для этого столбца показывает DateTimeOffset в качестве его типа.

[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.TableA")]
public partial class TableA : INotifyPropertyChanging, INotifyPropertyChanged {
    private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
    private int _Id;
    private System.DateTimeOffset _Created;

    etc

Я могу создать и выполнить запрос linq-to-sql на основе этих сгенерированных классов.

var query = db.TableA.Where(pt => pt.Created >= (DateTimeOffset) startTime && pt.Created <= endTime

Это переводит в правильный запрос SQL, но тип на стороне SQL DateTimeOffset(7). Поэтому база данных не использует оптимальное удаление разделов и обращается ко всем разделам. Если я изменю тип DateTimeOffset(3) на основе захваченного SQL-запроса и выполню в SSMS, он будет использовать исключение раздела.

exec sp_executesql N'SELECT TOP (10001) [t0].[Id], [t0].[Created], 
FROM [dbo].[TableA] AS [t0]
WHERE ([t0].[Created] >= @p0) AND ([t0].[Created] <= @p1) 
ORDER BY [t0].[Created] DESC',N'@p0 datetimeoffset(3),@p1 datetimeoffset(3)',@p0='2015-02-27 23:00:00 +00:00',@p1='2015-03-03 22:59:59 +00:00'

Так как же добиться оптимального исключения раздела? В моем примере мне понадобится доступ не более чем к двум разделам.

Я думал о создании хранимой процедуры, но это означало бы, что я потерял свою гибкость, позволяя легко изменять запрос в коде C#. Другим решением будет изменение типа SQL столбца Created на DateTimeOffset(7). Но недостатком этого является хранение избыточных данных о точности, которых у меня на самом деле нет.

Я хотел бы услышать о других возможностях, либо указав linq-to-sql, генерирующий DateTimeOffset(3) в качестве типа переменной SQL, либо другой способ сделать удаление разделов эффективным.

PS: я упростил определение таблицы и запросы для краткого определения проблемы.

1 ответ

Используйте форматирование DateTimeOffset.ToString по своему усмотрению.

DateTimeOffset outputDate = new DateTimeOffset(2007, 11, 1, 9, 0, 0, 
                                 new TimeSpan(-7, 0, 0)); 
string format = "dddd, MMM dd yyyy HH:mm:ss zzz";

// Output date and time using custom format specification
Console.WriteLine(outputDate.ToString(format, null as DateTimeFormatInfo));
Console.WriteLine(outputDate.ToString(format, CultureInfo.InvariantCulture));
Console.WriteLine(outputDate.ToString(format, 
                                  new CultureInfo("fr-FR")));
Console.WriteLine(outputDate.ToString(format, 
                                  new CultureInfo("es-ES")));
// The example displays the following output to the console: 
//    Thursday, Nov 01 2007 09:00:00 -07:00 
//    Thursday, Nov 01 2007 09:00:00 -07:00 
//    jeudi, nov. 01 2007 09:00:00 -07:00 
//    jueves, nov 01 2007 09:00:00 -07:00
Другие вопросы по тегам