EF 6 Объединять записи и обновлять все зависимые FK программно - PullRequest
0 голосов
/ 01 ноября 2018

Я хочу иметь возможность объединять дубликаты записей в 1 таблицу и обновлять все дочерние объекты, чей FK был originalRecordId, до destinyRecordId. Это можно сделать вручную, но это будет непростой задачей, поскольку родительская таблица может иметь более 40 связей, и это должно быть сделано в нескольких родительских таблицах. Я использую EF 6 с кодом в первую очередь.

Мне удалось получить все свойства навигации с помощью следующего (кредит переходит к @ zev-spits в этом вопросе):

public List<PropertyInfo> GetNavigationProperties(T entity)
{
    var t = entity.GetType();
    var elementType = ((IObjectContextAdapter)context).ObjectContext.CreateObjectSet<T>().EntitySet.ElementType;
    return elementType.NavigationProperties.Select(np => entityType.GetProperty(np.Name)).ToList();
}

Понятия не имею, куда идти отсюда.

Есть ли способ программно выполнить эту задачу? Я хотел бы передать в originalRecord и destinyRecord, получить все связанные сущности originalRecord и обновить FK с destinyRecordId.

1 Ответ

0 голосов
/ 05 ноября 2018

Я наконец-то принял предложение @mjwillis и решил это непосредственно в SQL Server следующим образом:

DECLARE @sql nvarchar (255);
DECLARE @refTableName varchar(255) = 'Opportunities'
DECLARE @refColName varchar(255) = 'Id'
DECLARE @refValue uniqueidentifier = '2a8a0f61-fe5c-4dd7-8e6d-00c8340333c4'

 Deleted User Key
DECLARE @refNewValue uniqueidentifier = '99999999-9999-9999-9999-999999999999'

DECLARE RelatedTableCursor CURSOR 
  LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
SELECT
    result.TableName,
    result.ColumnName
FROM
(
    SELECT
        OBJECT_NAME(f.parent_object_id) AS TableName,
        COL_NAME(fc.parent_object_id,fc.parent_column_id) AS ColumnName,
        SCHEMA_NAME(o.SCHEMA_ID) ReferenceSchemaName,
        OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
        COL_NAME(fc.referenced_object_id,fc.referenced_column_id) AS ReferenceColumnName
    FROM sys.foreign_keys AS f
    INNER JOIN sys.foreign_key_columns AS fc ON f.OBJECT_ID = fc.constraint_object_id
    INNER JOIN sys.objects AS o ON o.OBJECT_ID = fc.referenced_object_id
) result
WHERE
    ReferenceTableName = @refTableName AND ReferenceColumnName = @refColName

OPEN RelatedTableCursor
WHILE 1 = 1
BEGIN 
    DECLARE @tableName varchar(255)
    DECLARE @columnName varchar(255)

    FETCH NEXT FROM RelatedTableCursor into @tableName, @columnName

    IF @@fetch_status <> 0
    BEGIN
        BREAK
    END

    DECLARE @sql nvarchar (255);
    SET @sql = 
        N'UPDATE [' + @tableName + '] ' +
        'SET ' +
        '   [' + @columnName + '] = ''' + CONVERT(NVARCHAR(255), @refNewValue) + ''' ' +
        'WHERE [' + @columnName + '] = ''' + CONVERT(NVARCHAR(255), @refValue) + ''' ';

    -- Prevent some error (Duplicate record) that occurs when replace data in mapping table.
    BEGIN TRY
        -- exec sp_executesql @sql;
        select @sql
    END TRY
    BEGIN CATCH
    END CATCH
END
CLOSE RelatedTableCursor
DEALLOCATE RelatedTableCursor

SET @sql = 'DELETE FROM [' + @refTableName + '] WHERE ' + @refColName + ' = ''' + CONVERT(NVARCHAR(255), @refValue) + '''';
EXEC sp_executesql @sql;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...