Я на ранних стадиях преобразования приложения .NET Framework в .net 8+. Это поэтапный проект, поэтому на данном этапе я пытаюсь перейти от Entity Framework 6 на EF Core 3.1 (последняя версия, которая может нацелиться на .net Standard 2.0). < /P>
Существующее приложение делает некоторые странные вещи с столбцами идентификации. Вместо того, чтобы полагаться на реализацию идентификации идентификации SQL Server, iDbCommandTreeInterceptor и dbcommandInterceptor используется для перехвата оператора вставки и добавления пользовательского SQL для заполнения (и получения генерируемого значения) для любого столбца, который не в порядке, но идентификационный столб. Опция из -за ограничений вне моего контроля. Кроме того, следует отметить, что столбцы в базе данных не настроены в виде столбцов идентификации и не имеют значений по умолчанию. Вот как они настроены на модели EF.public class IdentityTreeInterceptor : IDbCommandTreeInterceptor
{
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
{
if (interceptionContext == null)
{
throw new ArgumentNullException(nameof(interceptionContext));
}
if (interceptionContext.OriginalResult.DataSpace == DataSpace.SSpace)
{
var insertCommand = interceptionContext.Result as DbInsertCommandTree;
if (insertCommand != null)
{
if (!HasPrimaryKeyClause(insertCommand))
{
bool hasChanges = false;
List revisedSetClauses =
new List(insertCommand.SetClauses)
{ CreateSetClauseForIdentityColumn(insertCommand, ref hasChanges) };
if (hasChanges)
{
var command = new DbInsertCommandTree(
insertCommand.MetadataWorkspace,
insertCommand.DataSpace,
insertCommand.Target,
new ReadOnlyCollection(revisedSetClauses),
insertCommand.Returning);
interceptionContext.Result = command;
}
}
}
}
}
private DbModificationClause CreateSetClauseForIdentityColumn(DbInsertCommandTree insertCommand, ref bool hasChanges)
{
EdmProperty keyMember = GetIdentityKey(insertCommand.Target.VariableType.EdmType);
if (keyMember != null && (keyMember.TypeName == "int" || keyMember.TypeName == "smallint"))
{
TypeUsage tableType = insertCommand.Target.VariableType;
string storeTableName = tableType.EdmType.MetadataProperties.GetValue("TableName", true).Value.ToString();
string storePkName = keyMember.Name;
string newIdSql = CreateNewIdStatement(keyMember, storeTableName, storePkName);
hasChanges = true;
return DbExpressionBuilder.SetClause(
DbExpressionBuilder.Property(
DbExpressionBuilder.Variable(tableType, insertCommand.Target.VariableName), keyMember.Name),
DbExpressionBuilder.Invoke(CreateFakeFunction(), DbExpression.FromString(newIdSql)));
}
return null;
}
private string CreateNewIdStatement(EdmProperty keyMember, string storeTableName, string storePrimaryKeyName)
{
if (ShouldUseSmallKey(keyMember.TypeName, storeTableName))
{
return $"DECLARE @newId smallint EXEC @newId = GetNextSmallKey '{storeTableName}', '{storePrimaryKeyName}';";
}
return $"DECLARE @newId int EXEC @newId = GetNextKey '{storeTableName}', '{storePrimaryKeyName}';";
}
private bool ShouldUseSmallKey(string keyType, string storeTableName)
{
return keyType == "smallint";
}
private bool HasPrimaryKeyClause(DbInsertCommandTree insertCommand)
{
string keyName = GetPrimaryKeyColumnName(insertCommand.Target.VariableType.EdmType);
foreach (DbSetClause setClause in insertCommand.SetClauses)
{
if (IsMatchingColumnName(setClause, keyName))
{
return true;
}
}
return false;
}
private string GetPrimaryKeyColumnName(EdmType tableSchema)
{
var keys = (IList)tableSchema.MetadataProperties.GetValue("KeyMembers", true).Value;
return (keys.Count == 1) ? keys[0].Name : null;
}
private bool IsMatchingColumnName(DbSetClause clause, string columnName)
{
if (!(clause.Property is DbPropertyExpression))
{
return false;
}
var expression = clause.Property as DbPropertyExpression;
string clauseColumnName = expression.Property.Name;
return columnName == clauseColumnName;
}
private EdmProperty GetIdentityKey(EdmType tableSchema)
{
var keys = (IList)tableSchema.MetadataProperties.GetValue("KeyMembers", true).Value;
if (keys.Count == 1 && keys[0].IsStoreGeneratedIdentity)
{
return keys[0] as EdmProperty;
}
return null;
}
private EdmFunction CreateFakeFunction()
{
FunctionParameter[] returnParameters = new FunctionParameter[]
{
FunctionParameter.Create("id", EdmType.GetBuiltInType(BuiltInTypeKind.FunctionParameter), ParameterMode.ReturnValue)
};
FunctionParameter[] parameters = new FunctionParameter[]
{
FunctionParameter.Create("fakeParam", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), ParameterMode.In)
};
var payload = new EdmFunctionPayload()
{
ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitConversion,
IsComposable = true,
Parameters = parameters,
ReturnParameters = returnParameters
};
return EdmFunction.Create("FakeFunction", "MyAppDb", DataSpace.SSpace, payload, null);
}
}
public class IdentitySqlInterceptor : DbCommandInterceptor
{
public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext interceptionContext)
{
if (command == null)
{
return;
}
int parmIndex = -1;
foreach (DbParameter parm in command.Parameters)
{
parmIndex++;
if (parm.Direction == ParameterDirection.Input && parm.Value.ToString().Contains("DECLARE @newId"))
{
Regex _regex = new Regex("(DECLARE @newId.*;)(.*)");
string newIdCommand = _regex.Match(parm.Value.ToString()).Result("$0");
command.CommandText = $"{newIdCommand} {command.CommandText.Replace($"@{parmIndex}", "@newId")}";
parm.Value = string.Empty;
break;
}
}
}
}
< /code>
Я попытался поиграть с пользовательскими генераторами значений, но они выполняются, когда элемент добавляется в контекст, а не когда фактические операторы вставки выполняются < /p>
Подробнее здесь: https://stackoverflow.com/questions/795 ... nterceptor
EF Core переопределить логику идентификации с использованием Interceptor ⇐ C#
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Spring MVC: как изменить @Pathvariable(URI) в Interceptor перед переходом к контроллеру?
Anonymous » » в форуме JAVA - 0 Ответы
- 29 Просмотры
-
Последнее сообщение Anonymous
-