Планирование пути с использованием 2D-массива

После небольшого исследования я смог использовать IsConcurrencyToken в столбце байта [8], названном RowVersion в Entity Framework 6.

Поскольку мы хотим использовать один и тот же тип данных в DB2 (который не имеют rowversion в самой базе данных), мы не можем использовать параметр IsRowVersion ()!

Я немного поработал над тем, как работать с IsConcurrencyToken.

Я сделал следующее для достижения решение, которое, кажется, работает:

Моя модель:

    public interface IConcurrencyEnabled
{
    byte[] RowVersion { get; set; }
}

  public class Product : AuditableEntity<Guid>,IProduct,IConcurrencyEnabled
{
    public string Name
    {
        get; set;
    }
    public string Description
    {
        get; set;
    }
    private byte[] _rowVersion = new byte[8];
    public byte[] RowVersion
    {
        get
        {
            return _rowVersion;
        }

        set
        {
            System.Array.Copy(value, _rowVersion, 8);
        }
    }
}

IConcurrencyEnabled используется для идентификации сущностей, которые имеют rowversion, которые нуждаются в особой обработке.

I использующий свободный API для конфигурирования конструктора:

    public class ProductConfiguration : EntityTypeConfiguration<Product>
{
    public ProductConfiguration()
    {
        Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        Property(e => e.RowVersion).IsFixedLength().HasMaxLength(8).IsConcurrencyToken();
    }
}

И, наконец, я добавил метод к моему производному классу DBContext для обновления поля до базы. ВызываетсяSaveChanges:

        public void OnBeforeSaveChanges(DbContext dbContext)
    {
        foreach (var dbEntityEntry in dbContext.ChangeTracker.Entries().Where(x => x.State == EntityState.Added || x.State == EntityState.Modified))
        {
            IConcurrencyEnabled entity = dbEntityEntry.Entity as IConcurrencyEnabled;
            if (entity != null)
            {

                if (dbEntityEntry.State == EntityState.Added)
                {
                    var rowversion = dbEntityEntry.Property("RowVersion");
                    rowversion.CurrentValue = BitConverter.GetBytes((Int64)1);
                }
                else if (dbEntityEntry.State == EntityState.Modified)
                {
                    var valueBefore = new byte[8];
                    System.Array.Copy(dbEntityEntry.OriginalValues.GetValue<byte[]>("RowVersion"), valueBefore, 8);

                    var value = BitConverter.ToInt64(entity.RowVersion, 0);
                    if (value == Int64.MaxValue)
                        value = 1;
                    else value++;

                    var rowversion = dbEntityEntry.Property("RowVersion");
                    rowversion.CurrentValue = BitConverter.GetBytes((Int64)value);
                    rowversion.OriginalValue = valueBefore;//This is the magic line!!

                }

            }
        }
    }

Проблема, с которой сталкивается большинство людей, заключается в том, что после установки значения сущности мы всегда получаем исключение UpdateDBConcurrencyException, потому что свойство OriginalValue изменилось ... даже если оно не было!

Причина в том, что для бют e [] как оригинал, так и currentValue, если вы установите CurrentValue отдельно (?? странное и неожиданное поведение).

Итак, я снова установил исходное значение в исходное значение перед обновлением rowversion ... Также я копирую массив, чтобы не ссылаться на один и тот же байт-массив!

Внимание: здесь я использую инкрементный подход для изменения rowversion, вы можете использовать свою собственную стратегию для заполнения этого значения. (Случайные или временные)

-2
задан eulerisgod 5 April 2019 в 08:23
поделиться

1 ответ

Вы должны либо хранить в какой-то очереди свои открытые узлы, либо каждый раз заполнять всю карту:

bool NextFill(int (&map)[MAX_SIZE][MAX_SIZE], int n)
{
    const int offx = {-1, 0, 0, 1};
    const int offy = {0, -1, 1, 0}
    bool found = false;
    for (int x = 0; x != MAX_SIZE; ++x) {
        for (int y = 0; y != MAX_SIZE; ++y) {
            if (map[x][y] == n) {
                 for (int i = 0; i != 4) {
                     auto& neighbor = map[x + offx[i]][y + offy[i]];

                     if (neighbor == -1) { /*Nothing*/ } // wall
                     else if (neighbor == -2) { found = true; } // Found
                     else if (neighbor == 0) { neighbor = n + 1; } // unvisited
                     // else {/*Nothing*/} // Already visited.
                 }
            }
        }
    }
    return found;
}
0
ответ дан Jarod42 5 April 2019 в 08:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: