【问题标题】:LINQ2SQL: How to implement a generic maximum string length validation?LINQ2SQL:如何实现通用的最大字符串长度验证?
【发布时间】:2009-07-23 14:39:43
【问题描述】:

LINQ2SQL 中的一个常见问题是,当 .NET 字符串允许为其变量分配任意长度时,您的数据库可能具有特定的最大长度约束(如 VARCHAR(5))。这将导致 SQL 错误消息“字符串或二进制数据将被截断。”,这是非常无益的,因为它不会告诉您哪些字段是罪魁祸首。

显然,验证输入的最大字符串长度将是正确的方法。我面临的主要问题是为项目中的每个 LINQ 对象创建必要的验证,并在字段的最大长度更新时更新验证。

理想情况下,我需要找到一种动态确定生成字段的最大长度的方法,这样我就不会冒险忘记稍后更新验证。

目前我能找到的最好的实现是"Integrating xVal Validation with Linq-to-Sql",它已经远远优于我能想到的任何东西。唯一不确定的点是动态确定最大长度。

有没有人看到或实现过类似的东西?

【问题讨论】:

    标签: linq-to-sql validation


    【解决方案1】:

    LINQ2SQL 代码生成器在属性字段上放置一个属性,类似于:

    [Column(Storage="_Message", DbType="NVarChar(20)")]
    

    在运行时提取和使用这些信息会很简单:

    public class Row
    {
        // normally generated by LINQ2SQL
        [Column(Storage = "_Message", DbType = "NVarChar(20)")]
        public string Message
        {
            get;
            set;
        }
    
        // normally generated by LINQ2SQL
        [Column(Storage = "_Property", DbType = "NVarChar(20) NOT NULL")]
        public string Property
        {
            get;
            set;
        }
    }
    
    public class VarCharInfo
    {
        public int? MaxLen;
        public bool IsNullable;
    }
    
    public static VarCharInfo GetVarCharInfo(PropertyInfo propertyInfo)
    {
        var attrib = propertyInfo.GetCustomAttributes(typeof(ColumnAttribute), false)
            .OfType<ColumnAttribute>()
            .FirstOrDefault();
    
        if (attrib == null || attrib.DbType == null)
        {
            return null;
        }
    
        var match = Regex.Match(attrib.DbType, @"VarChar\((?'len'\d+)\)(?'notnull' NOT NULL)?");
    
        if (!match.Success)
        {
            return null;
        }
    
        var rvl = new VarCharInfo();
    
        rvl.MaxLen = int.Parse(match.Groups["len"].Captures[0].Value);
        rvl.IsNullable = match.Groups["notnull"].Success;
    
        return rvl;
    }
    
    public static bool ValidateVarCharColumns(object dataObject)
    {
        bool success = true;
    
        foreach (var propertyInfo in dataObject.GetType()
            .GetProperties()
            .Where(pi => pi.PropertyType == typeof(string)))
        {
            var vci = GetVarCharInfo(propertyInfo);
    
            if (vci != null)
            {
                var currentValue = propertyInfo.GetGetMethod()
                    .Invoke(dataObject, null) as string;
    
                if (currentValue == null)
                {
                    if (!vci.IsNullable)
                    {
                        // more work: value is null but it shouldn't be
                        success = false;
                    }
                }
                else if (vci.MaxLen != null && currentValue.Length > vci.MaxLen)
                {
                    // more work: value is longer than db allows
                    success = false;
                }
            }
        }
    
        return success;
    }
    
    static void UsageTest()
    {
        Row t = new Row();
        t.Message = "this message is longer than 20 characters";
        // t.Property is null
    
        ValidateVarCharColumns(t);  // returns false!
    }
    

    【讨论】:

    • 我已经使用我自己的 LINQ 对象对其进行了测试,它工作正常!通过一些修饰,这是一个非常简单的解决方案,可以满足我的大部分验证需求。谢谢!
    猜你喜欢
    • 2012-06-14
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    • 2019-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多