Optimistic concurrency - current state of support in dotConnect for SQLite?

Discussion of open issues, suggestions and bugs regarding ADO.NET provider for SQLite
Post Reply
talbrecht
Posts: 10
Joined: Wed 26 Oct 2016 14:06

Optimistic concurrency - current state of support in dotConnect for SQLite?

Post by talbrecht » Wed 07 Dec 2016 13:03

Hi,

what is the current state regarding optimistic concurrency support in dotConnect for SQLite?

In one of my quick'n'dirty test projects I was able to create a migration which contains:

Code: Select all

RowVersion = c.Binary(nullable: false, fixedLength: true, timestamp: true, storeType: "rowversion"),
This has made me curious if there is some optimistic concurrency support already.

According to the post SQLite + Code First: how to create 'RowVersion' columns ([Timestamp] annotation) there shouldn't be one.

In another project I've tried to enable optimistic concurrency the same way by configuring a property

Code: Select all

public byte[] RowVersion { get; set; }
as concurrency check property via

Code: Select all

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
      base.OnModelCreating(modelBuilder);

      modelBuilder.Entity<MyEntity>().Property(x => x.RowVersion).IsRowVersion();
    }
Unfortunately doing so breaks the migration support in that project:
System.InvalidOperationException: Sequence contains no matching element
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
at System.Data.Entity.Utilities.DbProviderManifestExtensions.GetStoreTypeFromName(DbProviderManifest providerManifest, String name)
at System.Data.Entity.ModelConfiguration.Configuration.Properties.Primitive.PrimitivePropertyConfiguration.ConfigureColumn(EdmProperty column, EntityType table, DbProviderManifest providerManifest)
at System.Data.Entity.ModelConfiguration.Configuration.Properties.Primitive.BinaryPropertyConfiguration.ConfigureColumn(EdmProperty column, EntityType table, DbProviderManifest providerManifest)
at System.Data.Entity.ModelConfiguration.Configuration.Properties.Primitive.PrimitivePropertyConfiguration.Configure(EdmProperty column, EntityType table, DbProviderManifest providerManifest, Boolean allowOverride, Boolean fillFromExistingConfiguration)
at System.Data.Entity.ModelConfiguration.Configuration.Properties.Primitive.PrimitivePropertyConfiguration.<>c__DisplayClass4.<Configure>b__3(Tuple`2 pm)
at System.Data.Entity.Utilities.IEnumerableExtensions.Each[T](IEnumerable`1 ts, Action`1 action)
at System.Data.Entity.ModelConfiguration.Configuration.Properties.Primitive.PrimitivePropertyConfiguration.Configure(IEnumerable`1 propertyMappings, DbProviderManifest providerManifest, Boolean allowOverride, Boolean fillFromExistingConfiguration)
at System.Data.Entity.ModelConfiguration.Configuration.Types.StructuralTypeConfiguration.ConfigurePropertyMappings(IList`1 propertyMappings, DbProviderManifest providerManifest, Boolean allowOverride)
at System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.ConfigurePropertyMappings(DbDatabaseMapping databaseMapping, EntityType entityType, DbProviderManifest providerManifest, Boolean allowOverride)
at System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.Configure(EntityType entityType, DbDatabaseMapping databaseMapping, DbProviderManifest providerManifest)
at System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.ConfigureEntityTypes(DbDatabaseMapping databaseMapping, ICollection`1 entitySets, DbProviderManifest providerManifest)
at System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.Configure(DbDatabaseMapping databaseMapping, DbProviderManifest providerManifest)
at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)
at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.LazyInternalContext.get_ModelBeingInitialized()
at System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(DbContext context, XmlWriter writer)
at System.Data.Entity.Utilities.DbContextExtensions.<>c__DisplayClass1.<GetModel>b__0(XmlWriter w)
at System.Data.Entity.Utilities.DbContextExtensions.GetModel(Action`1 writeXml)
at System.Data.Entity.Utilities.DbContextExtensions.GetModel(DbContext context)
at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration, DbContext usersContext, DatabaseExistenceState existenceState, Boolean calledByCreateDatabase)
at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration)
at System.Data.Entity.Migrations.Design.MigrationScaffolder..ctor(DbMigrationsConfiguration migrationsConfiguration)
at System.Data.Entity.Migrations.Design.ToolingFacade.ScaffoldRunner.Run()
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
at System.Data.Entity.Migrations.Design.ToolingFacade.Scaffold(String migrationName, String language, String rootNamespace, Boolean ignoreChanges)
at System.Data.Entity.Migrations.AddMigrationCommand.Execute(String name, Boolean force, Boolean ignoreChanges)
at System.Data.Entity.Migrations.AddMigrationCommand.<>c__DisplayClass2.<.ctor>b__0()
at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
Sequence contains no matching element
I do not know why I was able to create the migration in one project but fail in others. Does dotConnect for SQLite support optimistic concurrency now? And if yes, how can I set it up without breaking migration support?

Best regards
Thomas

Shalex
Site Admin
Posts: 9543
Joined: Thu 14 Aug 2008 12:44

Re: Optimistic concurrency - current state of support in dotConnect for SQLite?

Post by Shalex » Fri 09 Dec 2016 09:10

The SQLite engine itself doesn't support the rowversion column data type. Please use a solution described at viewtopic.php?f=29&t=33049 (also we have just resent you a test project from that thread):

Code: Select all

    public byte[] Token { get; set; }

Code: Select all

      private void ObjectContext_SavingChanges(object sender, EventArgs e) {
          ObjectContext context = (ObjectContext)sender;

          var addedOrModified = context.ObjectStateManager
            .GetObjectStateEntries(EntityState.Added | EntityState.Modified)
            .Where(entry => entry.Entity is Product)
            .Select(entry => (Product)entry.Entity)
            .ToList();

          foreach (Product item in addedOrModified) {
              item.Token = Guid.NewGuid().ToByteArray();
          }

          context.DetectChanges();
      }

talbrecht
Posts: 10
Joined: Wed 26 Oct 2016 14:06

Re: Optimistic concurrency - current state of support in dotConnect for SQLite?

Post by talbrecht » Fri 09 Dec 2016 10:12

Thanks for your response.

There is a small but important part missing in your answer* to get this working:

Code: Select all

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  base.OnModelCreating(modelBuilder);
  modelBuilder.Entity<Product>().Property(p => p.Token).IsConcurrencyToken();
}
or same effect with an attribute

Code: Select all

[ConcurrencyCheck]
public byte[] Token { get; set; }
I hope others will benefit from this solution, too.

*) The sent test project uses the non-attributed version.

Post Reply