Я пытаюсь получить DataTable
и обновить его позже в моей программе, однако я получаю System.Exception
при попытке изменить один из моих столбцов (IsUsed). Ошибка чтения: «Столбец IsUsed читается только'. Что верно, для столбца в DataTable
свойство ReadOnly
имеет значение true.
Вот мой код C #, который генерирует мой SQL:
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
в столбцах как ложное. Так что я знаю, что это как-то связано с профсоюзом, но я не уверен почему.
Я знаю, что этот вопрос задавался аналогичным образом ранее, но я не хочу зацикливаться на столбцах DataTable
и вручную устанавливать для свойства ReadOnly
значение true, я хотел бы устранить проблему на источник.
Спасибо!
ОБНОВЛЕНИЕ: Я полагаю, это потому, что столбцы классифицируются как «вычисляемые» столбцы, которые код C # по умолчанию будет читать только как true.