Переопределить Linq-to-Sql Datetime.ToString () Преобразование значений по умолчанию - PullRequest
0 голосов
/ 08 февраля 2011

Можно ли переопределить стиль по умолчанию CONVERT? Я бы хотел, чтобы функция по умолчанию CONVERT всегда возвращала стиль ISO8601 126.

Шаги для воспроизведения:

DROP TABLE DATES;

CREATE TABLE DATES
(
    ID INT IDENTITY(1,1) PRIMARY KEY,
    MYDATE DATETIME DEFAULT(GETUTCDATE())
);

INSERT INTO DATES DEFAULT VALUES;
INSERT INTO DATES DEFAULT VALUES;
INSERT INTO DATES DEFAULT VALUES;
INSERT INTO DATES DEFAULT VALUES;

SELECT CONVERT(NVARCHAR,MYDATE) AS CONVERTED, 
       CONVERT(NVARCHAR(4000),MYDATE,126) AS ISO, 
       MYDATE FROM DATES
WHERE MYDATE LIKE'Feb%'

Выход:

CONVERTED                   ISO                          MYDATE
--------------------------- ---------------------------- -----------------------
Feb  8 2011 12:17AM         2011-02-08T00:17:03.040      2011-02-08 00:17:03.040
Feb  8 2011 12:17AM         2011-02-08T00:17:03.040      2011-02-08 00:17:03.040
Feb  8 2011 12:17AM         2011-02-08T00:17:03.040      2011-02-08 00:17:03.040
Feb  8 2011 12:17AM         2011-02-08T00:17:03.040      2011-02-08 00:17:03.040

Linq-to-Sql звонит CONVERT(NVARCHAR,@p), когда я разыгрываю ToString(). Тем не менее, я отображаю все свои данные в формате ISO8601. Я хотел бы переопределить базу данных по умолчанию, если это возможно, CONVERT(NVARCHAR,@p,126).

Я использую Dynamic Linq-to-Sql для демонстрации ScottGu для обработки моих данных.

PropertyInfo piField = typeof(T).GetProperty(rule.field);
if (piField != null)
{
    Type typeField = piField.PropertyType;
    if (typeField.IsGenericType && typeField.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
    {
        filter = filter
           .Select(x => x)
           .Where(string.Format("{0} != null", rule.field))
           .Where(string.Format("{0}.Value.ToString().Contains(\"{1}\")", rule.field, rule.data));
    }
    else
    {
        filter = filter
            .Select(x => x)
            .Where(string.Format("{0} != null", rule.field))
            .Where(string.Format("{0}.ToString().Contains(\"{1}\")", rule.field, rule.data));
    }
} 

Я надеялся, что моя собственность преобразует выражение из CONVERT(NVARCHAR,@p) в CONVERT(NVARCHAR,@p,126), однако я получаю NotSupportedException: ... has no supported translation to SQL.

public string IsoDate
{
    get
    {
        if (SUBMIT_DATE.HasValue)
        {
            return SUBMIT_DATE.Value.ToString("o");
        }
        else
        {
            return string.Empty;
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 27 февраля 2011

Вместо использования динамического linq я использовал построитель выражений. См. Ilya Builuk's Использование панели инструментов поиска jqGrid с несколькими фильтрами в ASP.NET MVC , обнаруженной в codeproject . Он строит выражения динамически на основе параметров класса. Очевидно, я не мог использовать «содержит», но я мог использовать выражения больше или меньше.

Вы можете заменить WhereOperation строкой. В этом конкретном примере это перечисление.

Я реализовал большее и меньшее количество выражений и смог сузить поиск, а не использовать слова «содержит».

public static class LinqExtensions
{  
    public static IQueryable<T> Where<T>(this IQueryable<T> query,
        string column, object value, WhereOperation operation)
    {
        if (string.IsNullOrEmpty(column))
            return query;

        ParameterExpression parameter = Expression.Parameter(query.ElementType, "p");

        MemberExpression memberAccess = null;
        foreach (var property in column.Split('.'))
            memberAccess = MemberExpression.Property
               (memberAccess ?? (parameter as Expression), property);

        //change param value type
        //necessary to getting bool from string
        ConstantExpression filter = Expression.Constant
            (
                Convert.ChangeType(value, memberAccess.Type)
            );

        //switch operation
        Expression condition = null;
        LambdaExpression lambda = null;
        switch (operation)
        {
            //equal ==
            case WhereOperation.Equal:
                condition = Expression.Equal(memberAccess, filter);
                lambda = Expression.Lambda(condition, parameter);
                break;
            //not equal !=
            case WhereOperation.NotEqual:
                condition = Expression.NotEqual(memberAccess, filter);
                lambda = Expression.Lambda(condition, parameter);
                break;
            //string.Contains()
            case WhereOperation.Contains:
                condition = Expression.Call(memberAccess,
                    typeof(string).GetMethod("Contains"),
                    Expression.Constant(value));
                lambda = Expression.Lambda(condition, parameter);
                break;
        }


        MethodCallExpression result = Expression.Call(
               typeof(Queryable), "Where",
               new[] { query.ElementType },
               query.Expression,
               lambda);

        return query.Provider.CreateQuery<T>(result);
    }
}
0 голосов
/ 08 февраля 2011

Это, вероятно, выстрел в темноте, но помогает ли эта ссылка?

Учитывая объект DateTime, как мне получить дату ISO 8601 в строковом формате?

...