覆盖Linq-to-Sql Datetime.ToString()默认转换值

时间:2011-02-08 00:33:36

标签: c# sql-server linq-to-sql sql-server-2000

是否可以覆盖默认的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

当我投射CONVERT(NVARCHAR,@p)时,Linq-to-Sql调用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 :(得分:0)

它可能在黑暗中拍摄,但这个链接有帮助吗?

Given a DateTime object, how do I get an ISO 8601 date in string format?

答案 1 :(得分:0)

我没有使用动态linq,而是使用了表达式构建器。请参阅codeproject上的 Ilya Builuk的 使用jqGrid的搜索工具栏以及ASP.NET MVC中的多个过滤器。它基于类参数动态构建表达式。显然我不能使用“包含”但我可以使用大于或小于表达式。

您可以使用字符串替换WhereOperation。在这个特定的例子中,它是一个枚举。

我实现了越来越少的表达式,我能够缩小搜索范围,而不是使用单词contains。

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);
    }
}