2010-12-12 4 views
0

Je n'ai pas pu insérer de données dans une table avec une colonne calculée à l'aide de Subsonic. Est-ce un bug bien connu? Et comment je peux le résoudre?Colonnes calculées dans SQL Server avec Subsonic

+0

Lorsque vous insérez des données dans une table, assurez-vous ** ** pas de fournir une valeur pour la colonne calculée. En langage SQL, assurez-vous de ne pas avoir cette colonne dans votre instruction INSERT (...). Je ne sais pas comment vous pourriez le faire dans SubSonic, bien que .... (btw: v2 ou v3? Bêtes assez différentes ....) –

+0

SubSonic v3. Il génère une commande SQL INSERT incluant une colonne calculée. Je ne sais pas comment forcer SubSonic à générer la commande INSERT sans cette colonne. – Anton

Répondre

1

Ce code SubSonic va à l'encontre de la db pour déterminer si elle est une colonne calculée:

const string [email protected]"SELECT 
     TABLE_CATALOG AS [Database], 
     TABLE_SCHEMA AS Owner, 
     TABLE_NAME AS TableName, 
     COLUMN_NAME AS ColumnName, 
     ORDINAL_POSITION AS OrdinalPosition, 
     COLUMN_DEFAULT AS DefaultSetting, 
     IS_NULLABLE AS IsNullable, DATA_TYPE AS DataType, 
     CHARACTER_MAXIMUM_LENGTH AS MaxLength, 
     DATETIME_PRECISION AS DatePrecision, 
     COLUMNPROPERTY(object_id('[' + TABLE_SCHEMA + '].[' + TABLE_NAME + ']'), COLUMN_NAME, 'IsIdentity') AS IsIdentity, 
     COLUMNPROPERTY(object_id('[' + TABLE_SCHEMA + '].[' + TABLE_NAME + ']'), COLUMN_NAME, 'IsComputed') as IsComputed 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE [email protected] 
    ORDER BY OrdinalPosition ASC"; 

Cette déclaration devrait intéresser:

COLUMNPROPERTY(object_id('[' + TABLE_SCHEMA + '].[' + TABLE_NAME + ']'), 
     COLUMN_NAME, 'IsComputed') as IsComputed 

Tout d'abord vous devez exécuter que contre votre db pour déterminer si le résultat est vrai.

La deuxième chose que je remarque est que, même si cette valeur est interrogé à partir du db, il est pas défini dans le code:

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

Le code est de https://github.com/subsonic/SubSonic-3.0-Templates/blob/master/ActiveRecord/SQLServer.ttinclude

Vous devez modifier votre copie locale du SQLServer.ttinclude et ajouter une ligne (avant que la méthode result.Add (col)) qui ressemble à ceci:

col.IsComputed=rdr["IsComputed"].ToString()=="1"; 

(en fonction du résultat de la requête, il c Soit "OUI" au lieu de "1"). L'objet de la colonne a une propriété IsComputed,

https://github.com/subsonic/SubSonic-3.0/blob/master/SubSonic.Core/Schema/IColumn.cs

mais encore une fois, je ne sais pas si elle est respectée lors de la mise à jour/insertion.
Si ce n'est pas le cas, essayez de définir col.IsReadOnly sur true.

Une dernière chose. Si la modification SQLServer.ttinclude résout votre problème, vous devez ajouter une demande de pull à la page github subsonique.

Edit: Avant de déconner avec le SQLServer.ttinclude vous pouvez ajouter le

col.IsComputed = true; 

ligne directement à vous votre fichier Structs.cs (mais il sera la prochaine fois surchargée vous exécutez le modèle).

0

Je reçois toujours cette erreur lors de l'insertion (Ajout) d'une ligne dans une table SQL avec une colonne calculée:

System.Data.SqlClient.SqlException: The column "{0}" cannot be modified because it is either a computed column or is the result of a UNION operator. 

Quelqu'un at-il fait des progrès à ce sujet ou est-ce encore un bug? En utilisant Subsonic.Core Version 3.0.0.3. J'ai suivi le très bon conseil de SchlaWiener, mais hélas, comme il l'a peut-être suspecté, même ajouter IsComputed = true, ou même IsReadOnly = true manuellement au fichier Structs.cs semble toujours émettre la colonne calculée dans l'INSERT déclaration et donc le bug existe toujours. Je n'ai pas téléchargé et vérifié le code source de Subversion pour voir si les colonnes IsComputed ou IsReadOnly sont ignorées, mais en fonction de l'expérimentation, elles semblent être incluses dans l'instruction INSERT et sont donc la source d'un défaut gênant.

Est-ce que quelqu'un connaît des solutions de contournement?

Merci. PS pour ce que ça vaut, j'ai soumis un problème 275 dans github ... Si j'étais plus confiant, je ferais le correctif ... Je pourrais essayer le suivant. BTW FWIW: commentant la propriété dans le ActiveRecord.cs fait disparaître le problème (temporairement, jusqu'à ce que vous réexécutez vos modèles T-4) ET tant que vous lisez cette propriété via un proc stocké. https://github.com/subsonic/SubSonic-3.0/issues/275

1

Je fixe ce peut-être .... Au deuxième tour SQLSErver.ttinclude à propos de la ligne 171 J'ai changé

 col.AutoIncrement=rdr["IsIdentity"].ToString()=="1"; 

à col.AutoIncrement = rdr [ "IsIdentity"]. ToString() = = "1" || rdr ["IsComputed"]. ToString() == "1";

Maintenant, je déteste cela comme une solution, mais la classe de colonne n'a pas une propriété pour IsComputer (ou IsReadOnly) donc ce au moins arrêté les inserts de ne pas

espoir qui aide - se poster à nouveau si je trouver une meilleure solution

Mike

Questions connexes