带有Subsonic的SQL Server中的计算列

时间:2010-12-12 19:42:14

标签: sql-server-2005 subsonic

我无法使用Subsonic将数据插入带有计算列的表中。这是众所周知的bug吗?我怎么解决它?

3 个答案:

答案 0 :(得分:1)

这是SubSonic针对db运行的代码,以确定它是否为计算列:

const string COLUMN_SQL=@"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 TABLE_NAME=@tableName
    ORDER BY OrdinalPosition ASC";

该声明应引起关注:

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

首先,您应该针对数据库运行该操作,以确定结果是否为真。

我注意到的第二件事是,即使从db中查询了这个值,它也没有在代码中设置:

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

代码来自https://github.com/subsonic/SubSonic-3.0-Templates/blob/master/ActiveRecord/SQLServer.ttinclude

您应该修改SQLServer.ttinclude的本地副本,并添加一行(在result.Add(col)方法之前),如下所示:

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

(取决于查询的结果,它可能是“YES”而不是“1”)。 Column对象具有IsComputed属性

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

但是,我不知道在更新/插入期间是否尊重它 如果不是,请尝试将col.IsReadOnly设置为true。

最后一件事。 如果SQLServer.ttinclude修改修复了您的问题,您应该向子声道github页面添加一个拉取请求。

修改 在搞乱SQLServer.ttinclude之前,你可以添加

col.IsComputed = true;

直接将您的Structs.cs文件排成行(但下次执行模板时会覆盖它)。

答案 1 :(得分:1)

我已经解决了这个问题.... 在SQLSErver.ttinclude围绕第171行进行了更改

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

要          col.AutoIncrement = rdr [“IsIdentity”]。ToString()==“1”|| RDR [ “IsComputed”]的ToString()== “1”;

现在我讨厌这个解决方案,但Column类没有IsComputer的属性  (或IsReadOnly) 所以这至少阻止了插入失败

希望有帮助 - 如果我找到更好的解决方案,将再次发布

麦克

答案 2 :(得分:0)

将一行插入(添加)到具有计算列的SQL表中时,我仍然会收到此错误:

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.

有没有人在这方面取得任何进展或这仍然是一个错误?使用Subsonic.Core版本3.0.0.3。

我遵循了SchlaWiener的非常好的建议,但是,他/她可能已经怀疑,甚至将IsComputed = true,甚至IsReadOnly = true手动添加到Structs.cs文件似乎仍然在INSERT语句中发出计算列因此bug仍然存在。

我没有下载并检查Subversion源代码以查看是否忽略了IsComputed或IsReadOnly列,但是基于实验,它们似乎包含在INSERT语句中,因此是恼人缺陷的来源。

有没有人知道任何变通办法?

感谢。

PS值得我在github上提交了一个问题275 ...如果我更自信我会做出修复......我可能会尝试下一步。 BTW FWIW:在ActiveRecord.cs中注释掉该属性会使问题消失(暂时,直到您重新运行T-4模板)并且只要您通过存储过程读取该属性即可。 https://github.com/subsonic/SubSonic-3.0/issues/275