【发布时间】:2018-11-01 18:18:16
【问题描述】:
我正在尝试获取 DataTable 并稍后在我的程序中更新它,但是当我尝试修改我的一个列 (IsUsed) 时收到 System.Exception。错误显示“已读取列 IsUsed只要'。这是真的,DataTable 中的列将ReadOnly 属性设置为 true。
这是生成我的 SQL 的 C# 代码:
public IgnoredPositionSet GetAllForReconciliation(int aReconciliationId)
{
SqlGenerator internalIgnoredPositionSqlGenerator = base.GetCoreSqlGenerator()
.Select.Add(@"
IP.SecurityId,
IP.SecurityName,
IP.Quantity,
NULL AS AccountTypeName")
.Join.Add($@"
LEFT JOIN
(
SELECT
ReconciliationId,
MatchId,
SecurityId,
SecurityName,
SUM(QuantityTradeDate) AS Quantity
FROM [PositionReconciliation.InternalPosition]
GROUP BY
ReconciliationId,
MatchId,
SecurityId,
SecurityName
) IP
ON IP.ReconciliationId = {ServiceTableAlias}.ReconciliationId
AND IP.MatchId = {ServiceTableAlias}.MatchId")
.Where.Add("IsInternalPosition = 1");
SqlGenerator externalIgnoredPositionSqlGenerator = GetCoreSqlGenerator()
.Select.Add(@"
NULL AS SecurityId,
EP.SecurityName,
EP.Quantity,
AccountTypeName")
.Join.Add($@"
LEFT JOIN
(
SELECT
ReconciliationId,
MatchId,
SecurityName,
SUM(QuantityTradeDate) AS Quantity
FROM [PositionReconciliation.ExternalPosition]
GROUP BY
ReconciliationId,
MatchId,
SecurityName
) EP
ON EP.ReconciliationId = {ServiceTableAlias}.ReconciliationId
AND EP.MatchId = {ServiceTableAlias}.MatchId")
.Join.Add($@"
LEFT JOIN
(
SELECT
EP.ReconciliationId,
EP.MatchId,
A.AccountTypeId,
AT.Name AS AccountTypeName
FROM [PositionReconciliation.ExternalPosition] EP
LEFT JOIN [Core.CustodianFund.AccountMap] A ON A.Id = EP.CustodianAccountId
LEFT JOIN [Reconciliation.Cash.AccountType] AT ON AT.Id = A.AccountTypeId
GROUP BY ReconciliationId, MatchId, AccountTypeId, AT.Name
) EPAT
ON EPAT.ReconciliationId = {ServiceTableAlias}.ReconciliationId
AND EPAT.MatchId = {ServiceTableAlias}.MatchId")
.Where.Add("IsInternalPosition = 0");
var internalPositions = GetEntitySet(internalIgnoredPositionSqlGenerator); //ReadOnly props are false
var externalPositions = GetEntitySet(externalIgnoredPositionSqlGenerator); //ReadOnly props are false
return GetEntitySet($"SELECT * FROM ({internalIgnoredPositionSqlGenerator} UNION ALL {externalIgnoredPositionSqlGenerator}) {ServiceTableAlias} WHERE {nameof(IgnoredPosition.ReconciliationId)} = {aReconciliationId}");
生成的 SQL 如下所示:
SELECT
SERVICE_TABLE.*,
IP.SecurityId,
IP.SecurityName,
IP.Quantity,
NULL AS AccountTypeName
FROM [PositionReconciliation.IgnoredPosition] SERVICE_TABLE
LEFT JOIN
(
SELECT
ReconciliationId,
MatchId,
SecurityId,
SecurityName,
SUM(QuantityTradeDate) AS Quantity
FROM [PositionReconciliation.InternalPosition]
GROUP BY
ReconciliationId,
MatchId,
SecurityId,
SecurityName
) IP
ON IP.ReconciliationId = SERVICE_TABLE.ReconciliationId
AND IP.MatchId = SERVICE_TABLE.MatchId
WHERE
(IsInternalPosition = 1)
UNION ALL
SELECT
SERVICE_TABLE.*,
NULL AS SecurityId,
EP.SecurityName,
EP.Quantity,
AccountTypeName
FROM [PositionReconciliation.IgnoredPosition] SERVICE_TABLE
LEFT JOIN
(
SELECT
ReconciliationId,
MatchId,
SecurityName,
SUM(QuantityTradeDate) AS Quantity
FROM [PositionReconciliation.ExternalPosition]
GROUP BY
ReconciliationId,
MatchId,
SecurityName
) EP
ON EP.ReconciliationId = SERVICE_TABLE.ReconciliationId
AND EP.MatchId = SERVICE_TABLE.MatchId
LEFT JOIN
(
SELECT
EP.ReconciliationId,
EP.MatchId,
A.AccountTypeId,
AT.Name AS AccountTypeName
FROM [PositionReconciliation.ExternalPosition] EP
LEFT JOIN [Core.CustodianFund.AccountMap] A ON A.Id = EP.CustodianAccountId
LEFT JOIN [Reconciliation.Cash.AccountType] AT ON AT.Id = A.AccountTypeId
GROUP BY ReconciliationId, MatchId, AccountTypeId, AT.Name
) EPAT
ON EPAT.ReconciliationId = SERVICE_TABLE.ReconciliationId
AND EPAT.MatchId = SERVICE_TABLE.MatchId
WHERE
(IsInternalPosition = 0)
这是创建DataSet的代码:
public DataSet GetDataSet(string aCommandText,
IEnumerable<DbDataParameter> aParameters = null,
int? aCommandTimeoutSeconds = null,
bool aIsUpdateable = true)
{
var da
taSet = new DataSet
{
Locale = CultureInfo.InvariantCulture,
EnforceConstraints = false
};
return PerformDbOperation(new DbOperationInfo(aCommandText, aCommandTimeoutSeconds, aParameters),
aDbOperationInfo =>
{
DataAdapter.SelectCommand = aDbOperationInfo.Command;
DataAdapter.MissingSchemaAction = aIsUpdateable ? MissingSchemaAction.AddWithKey : MissingSchemaAction.Add;
DataAdapter.Fill(dataSet);
if (dataSet.Tables.Count > 0)
aDbOperationInfo.AffectedRowCount = dataSet.Tables[0].Rows.Count;
return dataSet;
});
}
我一直在玩这个,我发现如果没有union,DataTable 可以很好地填充并将列上的ReadOnly 属性设置为 false。所以我知道这与工会有关,但我不确定为什么。
我知道以前曾以类似的方式提出过这个问题,但我不想循环 DataTable 列并手动将 ReadOnly 属性设置为 true,我想在来源。
谢谢!
更新:我相信这是因为这些列被归类为“计算”列,C# 代码将默认只读为 true。
【问题讨论】: