我无法使用Subsonic将数据插入带有计算列的表中。这是众所周知的bug吗?我怎么解决它?
答案 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