2009-07-23 7 views
2

Un problème courant dans LINQ2SQL est que la chaîne .NET permet d'assigner n'importe quelle longueur à sa variable, votre base de données peut avoir une contrainte de longueur maximale spécifique (comme VARCHAR (5)). Cela conduira au message d'erreur SQL "Les données chaîne ou binaires seront tronquées.", Ce qui est extrêmement inutile, car il ne vous dit pas quels champs est le coupable.LINQ2SQL: Comment implémenter une validation de longueur de chaîne générique maximale?

Évidemment, la validation de l'entrée pour la longueur de chaîne maximale sera la bonne façon. Le principal problème que j'ai rencontré est de créer la validation nécessaire pour chaque objet LINQ dans mon projet, et de mettre à jour la validation si la longueur maximale du champ est mise à jour.

Idéalement, je dois trouver un moyen de déterminer dynamiquement la longueur maximale d'un champ généré, donc je ne risque pas d'oublier de mettre à jour la validation plus tard.

La meilleure implémentation que je puisse trouver jusqu'à présent est "Integrating xVal Validation with Linq-to-Sql", ce qui est déjà bien supérieur à tout ce que je peux penser. Le seul point incertain est la détermination dynamique de la longueur maximale.

Est-ce que quelqu'un a vu ou implanté quelque chose de similaire?

Répondre

2

Le générateur de code LINQ2SQL place un attribut sur les champs de propriétés similaires à:

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

Il serait facile d'extraire et d'utiliser ces informations lors de l'exécution:

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

Je l'ai testé à l'aide mes propres objets LINQ, et ça marche bien! Avec quelques retouches, c'est une solution assez simple qui répond à la plupart de mes besoins de validation. Je vous remercie! – alextansc

Questions connexes