2010-09-03 5 views
2

J'utilise Subsonic 3 (Active Record), VS2010, Framework 3.5 contre une base de données MySQL. Quelqu'un a nommé une colonne "chaîne". Je ne vous * * t pas. OK, j'ai nommé quelques objets de base de données quelques noms stupides (comme nommer une table SQL Server "User") avant mais ... c'mon! Et je ne peux pas changer la table en raison des dépendances dans l'application!Subsonic DAL échoue compilation sur les colonnes qui sont des mots-clés

OK, je me sens un peu mieux maintenant que je l'ai VENTED un peu grâce à l'écoute

Alors, bien sûr, dans le code généré je reçois des erreurs dans tous les sens des lignes comme:

private string string {}

Je ne vois pas cela comme un bug prioritaire pour Subsonic à moins que d'autres n'aient des problèmes similaires avec d'autres noms de colonnes. Avez-vous l'intention de faire quelque chose à ce sujet?

Merci

Paul

P.S. Je vais essayer de changer les autres développeurs, ou me permettre de changer le nom de la colonne, je sais que c'est la vraie solution, mais Subsonic pourrait gérer gracieusement les noms illégaux, peut-être quelque chose comme le .netTiers gère (ajouter _safeName au nom, il deviendrait alors string_safeName).

Répondre

0

Vous pouvez résoudre ce problème très facilement.

Ouvrez le fichier SQLServer.ttinclude. C'est un fichier modèle T4 que SubSonic utilise pour générer votre code.

Presque à mi-chemin vers le bas, sur la ligne 155, vous trouverez la fonction LoadColumns:

List<Column> LoadColumns(Table tbl){ 
    var result=new List<Column>(); 
    var cmd=GetCommand(COLUMN_SQL); 
    cmd.Parameters.AddWithValue("@tableName",tbl.Name); 

    using(IDataReader rdr=cmd.ExecuteReader(CommandBehavior.CloseConnection)){ 
     while(rdr.Read()){ 
      Column col=new Column(); 
      col.Name=rdr["ColumnName"].ToString(); 
      col.CleanName=CleanUp(col.Name); 
      col.DataType=rdr["DataType"].ToString(); 
      col.SysType=GetSysType(col.DataType); 
      col.DbType=GetDbType(col.DataType); 
      col.AutoIncrement=rdr["IsIdentity"].ToString()=="1"; 
      col.IsNullable=rdr["IsNullable"].ToString()=="YES"; 
      int.TryParse(rdr["MaxLength"].ToString(),out col.MaxLength); 

      result.Add(col); 
     } 

    } 

    return result; 
} 

ajouter simplement la logique dans cette fonction quand il attribue le nom de changer du nom de colonne dans votre base de données, « string ", à quelque chose d'un peu plus sain d'esprit.

List<Column> LoadColumns(Table tbl){ 
    var result=new List<Column>(); 
    var cmd=GetCommand(COLUMN_SQL); 
    cmd.Parameters.AddWithValue("@tableName",tbl.Name); 

    using(IDataReader rdr=cmd.ExecuteReader(CommandBehavior.CloseConnection)){ 
     while(rdr.Read()){ 
      Column col=new Column(); 

      var rawName = rdr["ColumnName"].ToString(); 
      if (rawName.Equals("string")) { 
       col.Name="StringColumn"; 
      } else { 
       col.Name=rawName; 
      } 

      col.CleanName=CleanUp(col.Name); 
      col.DataType=rdr["DataType"].ToString(); 
      col.SysType=GetSysType(col.DataType); 
      col.DbType=GetDbType(col.DataType); 
      col.AutoIncrement=rdr["IsIdentity"].ToString()=="1"; 
      col.IsNullable=rdr["IsNullable"].ToString()=="YES"; 
      int.TryParse(rdr["MaxLength"].ToString(),out col.MaxLength); 

      result.Add(col); 
     } 

    } 

    return result; 
} 

vous aussi, devaient mettre un certain temps en elle et en faire gérer tous les mots-clés (par exemple, par recherche dans un dictionnaire statique et changer les noms en ajoutant un suffixe commun ou substitution dictionnaire), vous pouvez ensuite soumettre Retournez un patch au projet et contribuez au lieu d'essayer de convaincre les autres développeurs de le faire.

1

J'ai peut-être mal utilisé la langue. Avant d'aller de l'avant et de faire des modifications, je voulais m'assurer que tout n'était pas prêt sur une liste de priorités quelque part ou en cours d'élaboration. Voici la façon dont je suis allé avec.

En Settings.ttinclude:

string[] reservedWords = new string[]{"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", 
      "class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", 
      "extern", "finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", 
      "is", "lock", "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", 
      "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", 
      "struct", "switch", "this", "throw", "try", "typeof", "unit", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", 
      "void", "volatile", "while", "FALSE", "TRUE", "yield", "by", "descending", "from", "group", "into", "orderby", "select", 
      "var", "where" }; 

string CleanUp(string tableName){ 
    string result=tableName; 

    //strip blanks 
    result=result.Replace(" ",""); 

    if(reservedWords.Contains(result)){ 
     result += "_SafeName"; 
    } 
    //put your logic here... 

    return result; 
} 

La fonction CleanUp fixe déjà les noms de table et de colonne, donc je mis là ma logique. J'espère avoir tous les mots réservés ...

Ceci est également sur un plus petit projet où la base de données est MySQL. Donc, ce hack/patch est uniquement pour C#/mysql, mais très facile à déplacer vers d'autres bases de données/langages.

0

Si vous changez la méthode LoadColumns vous aurez encore des problèmes sur les clés étrangères, mais vous pouvez remplacer votre méthode CleanUp (chaîne tableName) dans Setting.ttinclude à:

string CleanUp(string tableName){ 
     string result=tableName; 

     //strip blanks 
     result=result.Replace(" ",""); 

     //put your logic here... 
     if (reservedWords.Contains(result)) { 
      result = "_" + result; 
     } 

     return result; 
    } 

cela a fonctionné comme un charme pour moi.

Questions connexes