2009-07-23 8 views
2

LINQ2SQLの一般的な問題は、.NET文字列で変数に任意の長さを割り当てることができますが、データベースにVARCHAR(5)などの特定の最大長制約があることです。これは、SQLエラーメッセージ "文字列またはバイナリデータが切り捨てられる"につながります。これは、どのフィールドが原因であるかを教えてくれないため、非常に役に立たないものです。LINQ2SQL:一般的な最大文字列の長さの検証を実装する方法は?

明らかに、最大文字列長の入力を検証することは正しい方法です。私が直面した主な問題は、プロジェクトのすべてのLINQオブジェクトに対して必要な検証を作成し、フィールドの最大長が更新された場合に検証を更新することです。

理想的には、生成されたフィールドの最大長を動的に決定する方法を検討する必要があるため、後で検証を更新することを忘れるリスクはありません。

私が今までに見つけた最良の実装は、"Integrating xVal Validation with Linq-to-Sql"です。これは、私が考えることができるものよりはるかに優れています。唯一の不確実な点は、動的に最大長を決定することです。

誰も似たようなことを見たり実装したことがありますか?

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

実行時にこの情報を抽出し、使用するのは簡単だろう:

答えて

2

LINQ2SQLコード・ジェネレータは次のようにプロパティフィールドに属性を置く

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! 
} 
+0

私が使用してそれをテストしてみました私の独自のLINQオブジェクト、それは正常に動作します!いくつかのタッチアップで、私の検証ニーズの大部分を満たす非常に簡単なソリューションです。ありがとうございました! – alextansc

関連する問題