Можно ли автоматически внедрить идентификатор с определенным размером шага в EntityFramework 6? - PullRequest
0 голосов
/ 16 апреля 2019

Мне нужно начать свой идентификатор модели с 100'000 и увеличить его на 100'000 для каждого следующего элемента. Есть ли способ сделать это в EF6? Я уже искал решения для аннотаций и Fluent API, но ничего не смог найти.

Я нашел способ сделать это только в EF Core, но, похоже, в EF 6 подобного способа не было (https://docs.microsoft.com/en-us/ef/core/modeling/relational/sequences)

Текущая модель:

public class Bubble
{
    // Keys
    [Required]
    [Key]
    public Int64 BubbleId { get; set; }

    // Members (needs max. string length that you can set it to unique -> https://stackoverflow.com/questions/10614575/entity-framework-code-first-unique-column)
    [Required]
    [StringLength(450)]
    [Index(IsUnique = true)]
    public string BubbleName { get; set; }

    // Navigation propertys
    public virtual ICollection<BubbleNode> BubbleNodes { get; set; }
}

1 Ответ

0 голосов
/ 16 апреля 2019

Если вы начинаете со свежей схемы, то возможно перехватить создание схемы и изменить создание идентификатора. Если схема уже создана (т.е. в расчете на миграцию), то это не так. Например, SQL позволит повторно заполнить идентификатор, но не изменит приращение.

В этом примере используется таблица с именем [Somethings], которая проверяет, когда таблица создана, заменяя «IDENTITY» на IDENTITY (100000,100000), если она найдена. К сожалению, насколько мне известно, в EF 6 перехватчик не может быть присоединен / отсоединен от контекста, поэтому вы можете использовать флаг, чтобы гарантировать, что код проверки / замены перехватчика не запускается все время по умолчанию.

Чтобы перехватить создание схемы:

public class Interceptor : IDbCommandInterceptor
{

    void IDbCommandInterceptor.NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    { }

    void IDbCommandInterceptor.NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
        if (interceptionContext.DbContexts.OfType<SomethingDbContext>().Any(x => !x.ShouldIntercept))
            return;

        var regex = "NOT NULL IDENTITY,";
        var replacement = "NOT NULL IDENTITY(100000,100000),";
        if (command.CommandText.StartsWith("CREATE TABLE [dbo].[Somethings]"))
            command.CommandText = Regex.Replace(command.CommandText, regex, replacement);
    }

    void IDbCommandInterceptor.ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    { }

    void IDbCommandInterceptor.ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    { }

    void IDbCommandInterceptor.ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    { }

    void IDbCommandInterceptor.ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    { }
}

public class SomethingConfiguration : DbConfiguration
{
    public SomethingConfiguration()
    {
        AddInterceptor(new Interceptor());
    }
}

Тогда в вашем DbContext:

[DbConfigurationType(typeof(SomethingConfiguration))]
public class SomethingDbContext : DbContext
{
    public bool ShouldIntercept { get; set;} = false;
    //  .. DbSets, etc.
}

По умолчанию ваш DbContext не будет активно перехватывать команды команд, так как мы действительно хотим активировать эту проверку служебных данных только один раз. Когда ваше приложение запускается, вы можете инициализировать DbContext, установить дляInInIncept значение True, а затем выполнить простой запрос, который обеспечит выполнение проверки / создания схемы DbContext:

using (var context = new SomethingDbContext())
{
    context.ShouldIntercept = true;
    var test = context.Somethings.Any(); // Triggers schema check/creation.
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...