You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
EntityFrameworkCore.Jet/test/EFCore.Jet.FunctionalTests/JetValueGenerationScenarios...

884 lines
32 KiB
C#

// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using EntityFrameworkCore.Jet.Data;
using System.Linq;
using EntityFrameworkCore.Jet.FunctionalTests.TestUtilities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.TestUtilities;
using Xunit;
3 years ago
using NetTopologySuite.Geometries;
// ReSharper disable InconsistentNaming
namespace EntityFrameworkCore.Jet.FunctionalTests
{
public class JetValueGenerationScenariosTest
{
private const string DatabaseName = "JetValueGenerationScenariosTest";
// Positive cases
[ConditionalFact]
public void Insert_with_Identity_column()
{
3 years ago
using var testStore = JetTestStore.CreateInitialized(DatabaseName);
using (var context = new BlogContextIdentity(testStore.Name))
{
3 years ago
context.Database.EnsureCreatedResiliently();
3 years ago
context.AddRange(
new Blog { Name = "One Unicorn" }, new Blog { Name = "Two Unicorns" });
3 years ago
context.SaveChanges();
}
3 years ago
using (var context = new BlogContextIdentity(testStore.Name))
{
var blogs = context.Blogs.OrderBy(e => e.Id).ToList();
3 years ago
Assert.Equal(1, blogs[0].Id);
Assert.Equal(2, blogs[1].Id);
}
}
public class BlogContextIdentity : ContextBase
{
public BlogContextIdentity(string databaseName)
: base(databaseName)
{
}
}
[ConditionalFact]
public void Insert_with_explicit_non_default_keys()
{
3 years ago
using var testStore = JetTestStore.CreateInitialized(DatabaseName);
using (var context = new BlogContextNoKeyGeneration(testStore.Name))
{
3 years ago
context.Database.EnsureCreatedResiliently();
3 years ago
context.AddRange(
new Blog { Id = 66, Name = "One Unicorn" }, new Blog { Id = 67, Name = "Two Unicorns" });
3 years ago
context.SaveChanges();
}
3 years ago
using (var context = new BlogContextNoKeyGeneration(testStore.Name))
{
var blogs = context.Blogs.OrderBy(e => e.Id).ToList();
3 years ago
Assert.Equal(66, blogs[0].Id);
Assert.Equal(67, blogs[1].Id);
}
}
public class BlogContextNoKeyGeneration : ContextBase
{
public BlogContextNoKeyGeneration(string databaseName)
: base(databaseName)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Blog>()
.Property(e => e.Id)
.ValueGeneratedNever();
}
}
[ConditionalFact]
public void Insert_with_explicit_with_default_keys()
{
3 years ago
using var testStore = JetTestStore.CreateInitialized(DatabaseName);
using (var context = new BlogContextNoKeyGenerationNullableKey(testStore.Name))
{
3 years ago
context.Database.EnsureCreatedResiliently();
3 years ago
context.AddRange(
new NullableKeyBlog { Id = 0, Name = "One Unicorn" },
new NullableKeyBlog { Id = 1, Name = "Two Unicorns" });
3 years ago
context.SaveChanges();
}
3 years ago
using (var context = new BlogContextNoKeyGenerationNullableKey(testStore.Name))
{
var blogs = context.NullableKeyBlogs.OrderBy(e => e.Id).ToList();
3 years ago
Assert.Equal(0, blogs[0].Id);
Assert.Equal(1, blogs[1].Id);
}
}
public class BlogContextNoKeyGenerationNullableKey : ContextBase
{
public BlogContextNoKeyGenerationNullableKey(string databaseName)
: base(databaseName)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<NullableKeyBlog>()
.Property(e => e.Id)
.ValueGeneratedNever();
}
}
[ConditionalFact]
public void Insert_with_non_key_default_value()
{
3 years ago
using var testStore = JetTestStore.CreateInitialized(DatabaseName);
using (var context = new BlogContextNonKeyDefaultValue(testStore.Name))
{
3 years ago
context.Database.EnsureCreatedResiliently();
3 years ago
var blogs = new List<Blog>
{
new() { Name = "One Unicorn" },
new()
{
3 years ago
Name = "Two Unicorns",
CreatedOn = new DateTime(1969, 8, 3, 0, 10, 0)
}
};
3 years ago
context.AddRange(blogs);
3 years ago
context.SaveChanges();
3 years ago
Assert.NotEqual(new DateTime(), blogs[0].CreatedOn);
Assert.NotEqual(new DateTime(), blogs[1].CreatedOn);
}
3 years ago
using (var context = new BlogContextNonKeyDefaultValue(testStore.Name))
{
var blogs = context.Blogs.OrderBy(e => e.Name).ToList();
Assert.Equal(3, blogs.Count);
3 years ago
Assert.NotEqual(new DateTime(), blogs[0].CreatedOn);
Assert.Equal(new DateTime(1969, 8, 3, 0, 10, 0), blogs[1].CreatedOn);
Assert.Equal(new DateTime(1974, 8, 3, 0, 10, 0), blogs[2].CreatedOn);
3 years ago
blogs[0].CreatedOn = new DateTime(1973, 9, 3, 0, 10, 0);
3 years ago
blogs[1].Name = "X Unicorns";
3 years ago
blogs[2].Name = "Y Unicorns";
3 years ago
context.SaveChanges();
}
using (var context = new BlogContextNonKeyDefaultValue(testStore.Name))
{
var blogs = context.Blogs.OrderBy(e => e.Name).ToList();
Assert.Equal(3, blogs.Count);
Assert.Equal(new DateTime(1973, 9, 3, 0, 10, 0), blogs[0].CreatedOn);
Assert.Equal(new DateTime(1969, 8, 3, 0, 10, 0), blogs[1].CreatedOn);
Assert.Equal(new DateTime(1974, 8, 3, 0, 10, 0), blogs[2].CreatedOn);
}
}
public class BlogContextNonKeyDefaultValue : ContextBase
{
public BlogContextNonKeyDefaultValue(string databaseName)
: base(databaseName)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>(
b =>
{
b.Property(e => e.CreatedOn)
3 years ago
.HasDefaultValueSql("now()");
b.HasData(
new Blog
{
Id = 9979,
Name = "W Unicorns",
CreatedOn = new DateTime(1974, 8, 3, 0, 10, 0)
});
});
}
}
[ConditionalFact]
public void Insert_with_non_key_default_value_readonly()
{
using (var testStore = JetTestStore.CreateInitialized(DatabaseName))
{
using (var context = new BlogContextNonKeyReadOnlyDefaultValue(testStore.Name))
{
context.Database.EnsureCreatedResiliently();
context.AddRange(
new Blog { Name = "One Unicorn" },
new Blog { Name = "Two Unicorns" });
context.SaveChanges();
Assert.NotEqual(new DateTime(), context.Blogs.ToList()[0].CreatedOn);
}
DateTime dateTime0;
using (var context = new BlogContextNonKeyReadOnlyDefaultValue(testStore.Name))
{
var blogs = context.Blogs.OrderBy(e => e.Id).ToList();
dateTime0 = blogs[0].CreatedOn;
Assert.NotEqual(new DateTime(), dateTime0);
Assert.NotEqual(new DateTime(), blogs[1].CreatedOn);
blogs[0].Name = "One Pegasus";
blogs[1].CreatedOn = new DateTime(1973, 9, 3, 0, 10, 0);
context.SaveChanges();
}
using (var context = new BlogContextNonKeyReadOnlyDefaultValue(testStore.Name))
{
var blogs = context.Blogs.OrderBy(e => e.Id).ToList();
Assert.Equal(dateTime0, blogs[0].CreatedOn);
Assert.Equal(new DateTime(1973, 9, 3, 0, 10, 0), blogs[1].CreatedOn);
}
}
}
public class BlogContextNonKeyReadOnlyDefaultValue : ContextBase
{
public BlogContextNonKeyReadOnlyDefaultValue(string databaseName)
: base(databaseName)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.Property(e => e.CreatedOn)
.HasDefaultValueSql("now()")
.Metadata.SetBeforeSaveBehavior(PropertySaveBehavior.Throw);
}
}
[ConditionalFact]
public void Insert_and_update_with_computed_column()
{
using (var testStore = JetTestStore.CreateInitialized(DatabaseName))
{
using (var context = new BlogContextComputedColumn(testStore.Name))
{
context.Database.EnsureCreatedResiliently();
var blog = context.Add(
new FullNameBlog { FirstName = "One", LastName = "Unicorn" }).Entity;
context.SaveChanges();
Assert.Equal("One Unicorn", blog.FullName);
}
using (var context = new BlogContextComputedColumn(testStore.Name))
{
var blog = context.FullNameBlogs.Single();
Assert.Equal("One Unicorn", blog.FullName);
blog.LastName = "Pegasus";
context.SaveChanges();
Assert.Equal("One Pegasus", blog.FullName);
}
}
}
public class BlogContextComputedColumn : ContextBase
{
public BlogContextComputedColumn(string databaseName)
: base(databaseName)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var property = modelBuilder.Entity<FullNameBlog>()
.Property(e => e.FullName)
.HasComputedColumnSql("FirstName + ' ' + LastName")
.Metadata;
property.SetBeforeSaveBehavior(PropertySaveBehavior.Throw);
property.SetAfterSaveBehavior(PropertySaveBehavior.Throw);
}
}
// #6044
[ConditionalFact]
public void Insert_and_update_with_computed_column_with_function()
{
using (var testStore = JetTestStore.CreateInitialized(DatabaseName))
{
using (var context = new BlogContextComputedColumnWithFunction(testStore.Name))
{
context.Database.ExecuteSqlRaw
(
@"CREATE FUNCTION
`GetFullName`(@First NVARCHAR(MAX), @Second NVARCHAR(MAX))
RETURNS NVARCHAR(MAX) WITH SCHEMABINDING AS BEGIN RETURN @First + @Second END");
context.GetService<IRelationalDatabaseCreator>().CreateTables();
}
using (var context = new BlogContextComputedColumnWithFunction(testStore.Name))
{
var blog = context.Add(
new FullNameBlog { FirstName = "One", LastName = "Unicorn" }).Entity;
context.SaveChanges();
Assert.Equal("OneUnicorn", blog.FullName);
}
using (var context = new BlogContextComputedColumnWithFunction(testStore.Name))
{
var blog = context.FullNameBlogs.Single();
Assert.Equal("OneUnicorn", blog.FullName);
blog.LastName = "Pegasus";
context.SaveChanges();
Assert.Equal("OnePegasus", blog.FullName);
}
}
}
public class BlogContextComputedColumnWithFunction : ContextBase
{
public BlogContextComputedColumnWithFunction(string databaseName)
: base(databaseName)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<FullNameBlog>()
.Property(e => e.FullName)
.HasComputedColumnSql("`GetFullName`(`FirstName`, `LastName`)")
.Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Throw);
}
}
// #6044
[ConditionalFact]
public void Insert_and_update_with_computed_column_with_querying_function()
{
using (var testStore = JetTestStore.CreateInitialized(DatabaseName))
{
using (var context = new BlogContextComputedColumn(testStore.Name))
{
context.GetService<IRelationalDatabaseCreator>().CreateTables();
context.Database.ExecuteSqlRaw("ALTER TABLE FullNameBlogs DROP COLUMN FullName;");
context.Database.ExecuteSqlRaw(
@"CREATE FUNCTION `GetFullName`(@Id int)
RETURNS NVARCHAR(MAX) WITH SCHEMABINDING AS
BEGIN
DECLARE @FullName NVARCHAR(MAX);
SELECT @FullName = `FirstName` + `LastName` FROM `FullNameBlogs` WHERE `Id` = @Id;
RETURN @FullName
END");
context.Database.ExecuteSqlRaw("ALTER TABLE FullNameBlogs ADD FullName AS `GetFullName`(`Id`); ");
}
try
{
using (var context = new BlogContextComputedColumn(testStore.Name))
{
var blog = context.Add(
new FullNameBlog { FirstName = "One", LastName = "Unicorn" }).Entity;
context.SaveChanges();
Assert.Equal("OneUnicorn", blog.FullName);
}
using (var context = new BlogContextComputedColumn(testStore.Name))
{
var blog = context.FullNameBlogs.Single();
Assert.Equal("OneUnicorn", blog.FullName);
blog.LastName = "Pegasus";
context.SaveChanges();
Assert.Equal("OnePegasus", blog.FullName);
}
using (var context = new BlogContextComputedColumn(testStore.Name))
{
var blog1 = context.Add(
new FullNameBlog { FirstName = "Hank", LastName = "Unicorn" }).Entity;
var blog2 = context.Add(
new FullNameBlog { FirstName = "Jeff", LastName = "Unicorn" }).Entity;
context.SaveChanges();
Assert.Equal("HankUnicorn", blog1.FullName);
Assert.Equal("JeffUnicorn", blog2.FullName);
}
}
finally
{
using (var context = new BlogContextComputedColumn(testStore.Name))
{
context.Database.ExecuteSqlRaw("ALTER TABLE FullNameBlogs DROP COLUMN FullName;");
context.Database.ExecuteSqlRaw("DROP FUNCTION `GetFullName`;");
}
}
}
}
[ConditionalFact]
public void Insert_with_client_generated_GUID_key()
{
using (var testStore = JetTestStore.CreateInitialized(DatabaseName))
{
Guid afterSave;
using (var context = new BlogContextClientGuidKey(testStore.Name))
{
context.Database.EnsureCreatedResiliently();
var blog = context.Add(
new GuidBlog { Name = "One Unicorn" }).Entity;
var beforeSave = blog.Id;
var beforeSaveNotId = blog.NotId;
Assert.NotEqual(default, beforeSave);
Assert.NotEqual(default, beforeSaveNotId);
context.SaveChanges();
afterSave = blog.Id;
var afterSaveNotId = blog.NotId;
Assert.Equal(beforeSave, afterSave);
Assert.Equal(beforeSaveNotId, afterSaveNotId);
}
using (var context = new BlogContextClientGuidKey(testStore.Name))
{
Assert.Equal(afterSave, context.GuidBlogs.Single().Id);
}
}
}
public class BlogContextClientGuidKey : ContextBase
{
public BlogContextClientGuidKey(string databaseName)
: base(databaseName)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
=> modelBuilder.Entity<GuidBlog>(
eb =>
{
eb.HasAlternateKey(e => e.NotId);
eb.Property(e => e.NotId).ValueGeneratedOnAdd();
});
}
[ConditionalFact]
public void Insert_with_ValueGeneratedOnAdd_GUID_nonkey_property_throws()
{
using (var testStore = JetTestStore.CreateInitialized(DatabaseName))
{
using (var context = new BlogContextClientGuidNonKey(testStore.Name))
{
context.Database.EnsureCreatedResiliently();
var blog = context.Add(
new GuidBlog { Name = "One Unicorn" }).Entity;
Assert.Equal(default, blog.NotId);
// No value set on a required column
Assert.Throws<DbUpdateException>(() => context.SaveChanges());
}
}
}
public class BlogContextClientGuidNonKey : ContextBase
{
public BlogContextClientGuidNonKey(string databaseName)
: base(databaseName)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
=> modelBuilder.Entity<GuidBlog>().Property(e => e.NotId).ValueGeneratedOnAdd();
}
[ConditionalFact]
public void Insert_with_server_generated_GUID_key()
{
using (var testStore = JetTestStore.CreateInitialized(DatabaseName))
{
Guid afterSave;
using (var context = new BlogContextServerGuidKey(testStore.Name))
{
context.Database.EnsureCreatedResiliently();
var blog = context.Add(
new GuidBlog { Name = "One Unicorn" }).Entity;
var beforeSave = blog.Id;
var beforeSaveNotId = blog.NotId;
Assert.Equal(default, beforeSave);
Assert.Equal(default, beforeSaveNotId);
context.SaveChanges();
afterSave = blog.Id;
var afterSaveNotId = blog.NotId;
Assert.NotEqual(default, afterSave);
Assert.NotEqual(default, afterSaveNotId);
Assert.NotEqual(beforeSave, afterSave);
Assert.NotEqual(beforeSaveNotId, afterSaveNotId);
}
using (var context = new BlogContextServerGuidKey(testStore.Name))
{
Assert.Equal(afterSave, context.GuidBlogs.Single().Id);
}
}
}
public class BlogContextServerGuidKey : ContextBase
{
public BlogContextServerGuidKey(string databaseName)
: base(databaseName)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<GuidBlog>(
eb =>
{
eb.Property(e => e.Id)
3 years ago
.HasDefaultValueSql("GenGUID()");
eb.Property(e => e.NotId)
3 years ago
.HasDefaultValueSql("GenGUID()");
});
}
}
// Negative cases
[ConditionalFact]
public void Insert_with_explicit_non_default_keys_by_default()
{
3 years ago
using var testStore = JetTestStore.CreateInitialized(DatabaseName);
using var context = new BlogContext(testStore.Name);
context.Database.EnsureCreatedResiliently();
context.AddRange(
new Blog { Id = 1, Name = "One Unicorn" }, new Blog { Id = 2, Name = "Two Unicorns" });
// DbUpdateException : An error occurred while updating the entries. See the
// inner exception for details.
// SqlException : Cannot insert explicit value for identity column in table
// 'Blog' when IDENTITY_INSERT is set to OFF.
context.Database.CreateExecutionStrategy().Execute(
context, c => {
var updateException = Assert.Throws<DbUpdateException>(() => c.SaveChanges());
Assert.Single(updateException.Entries);
});
}
[ConditionalFact]
public void Insert_with_explicit_default_keys()
{
3 years ago
using var testStore = JetTestStore.CreateInitialized(DatabaseName);
using var context = new BlogContext(testStore.Name);
context.Database.EnsureCreatedResiliently();
context.AddRange(
new Blog { Id = 0, Name = "One Unicorn" }, new Blog { Id = 1, Name = "Two Unicorns" });
// DbUpdateException : An error occurred while updating the entries. See the
// inner exception for details.
// SqlException : Cannot insert explicit value for identity column in table
// 'Blog' when IDENTITY_INSERT is set to OFF.
var updateException = Assert.Throws<DbUpdateException>(() => context.SaveChanges());
Assert.Single(updateException.Entries);
}
public class BlogContext : ContextBase
{
public BlogContext(string databaseName)
: base(databaseName)
{
}
}
[ConditionalFact]
public void Insert_with_implicit_default_keys()
{
using (var testStore = JetTestStore.CreateInitialized(DatabaseName))
{
using (var context = new BlogContextSpecifyKeysUsingDefault(testStore.Name))
{
context.Database.EnsureCreatedResiliently();
context.AddRange(
new Blog { Id = 0, Name = "One Unicorn" }, new Blog { Id = 1, Name = "Two Unicorns" });
context.SaveChanges();
}
using (var context = new BlogContextSpecifyKeysUsingDefault(testStore.Name))
{
var blogs = context.Blogs.OrderBy(e => e.Id).ToList();
Assert.Equal(0, blogs[0].Id);
Assert.Equal(1, blogs[1].Id);
}
}
}
public class BlogContextSpecifyKeysUsingDefault : ContextBase
{
public BlogContextSpecifyKeysUsingDefault(string databaseName)
: base(databaseName)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Blog>()
.Property(e => e.Id)
.ValueGeneratedNever();
}
}
[ConditionalFact]
public void Insert_explicit_value_throws_when_readonly_before_save()
{
using (var testStore = JetTestStore.CreateInitialized(DatabaseName))
{
using (var context = new BlogContextNonKeyReadOnlyDefaultValue(testStore.Name))
{
context.Database.EnsureCreatedResiliently();
context.AddRange(
new Blog { Name = "One Unicorn" },
new Blog { Name = "Two Unicorns", CreatedOn = new DateTime(1969, 8, 3, 0, 10, 0) });
// The property 'CreatedOn' on entity type 'Blog' is defined to be read-only before it is
// saved, but its value has been set to something other than a temporary or default value.
Assert.Equal(
CoreStrings.PropertyReadOnlyBeforeSave("CreatedOn", "Blog"),
Assert.Throws<InvalidOperationException>(() => context.SaveChanges()).Message);
}
}
}
[ConditionalFact]
public void Insert_explicit_value_into_computed_column()
{
using (var testStore = JetTestStore.CreateInitialized(DatabaseName))
{
using (var context = new BlogContextComputedColumn(testStore.Name))
{
context.Database.EnsureCreatedResiliently();
context.Add(
new FullNameBlog
{
FirstName = "One",
LastName = "Unicorn",
FullName = "Gerald"
});
// The property 'FullName' on entity type 'FullNameBlog' is defined to be read-only before it is
// saved, but its value has been set to something other than a temporary or default value.
Assert.Equal(
CoreStrings.PropertyReadOnlyBeforeSave("FullName", "FullNameBlog"),
Assert.Throws<InvalidOperationException>(() => context.SaveChanges()).Message);
}
}
}
[ConditionalFact]
public void Update_explicit_value_in_computed_column()
{
using (var testStore = JetTestStore.CreateInitialized(DatabaseName))
{
using (var context = new BlogContextComputedColumn(testStore.Name))
{
context.Database.EnsureCreatedResiliently();
context.Add(
new FullNameBlog { FirstName = "One", LastName = "Unicorn" });
context.SaveChanges();
}
using (var context = new BlogContextComputedColumn(testStore.Name))
{
var blog = context.FullNameBlogs.Single();
blog.FullName = "The Gorilla";
// The property 'FullName' on entity type 'FullNameBlog' is defined to be read-only after it has been saved,
// but its value has been modified or marked as modified.
Assert.Equal(
CoreStrings.PropertyReadOnlyAfterSave("FullName", "FullNameBlog"),
Assert.Throws<InvalidOperationException>(() => context.SaveChanges()).Message);
}
}
}
// Concurrency
[ConditionalFact]
public void Resolve_concurrency()
{
3 years ago
using var testStore = JetTestStore.CreateInitialized(DatabaseName);
using var context = new BlogContextConcurrencyWithRowversion(testStore.Name);
context.Database.EnsureCreatedResiliently();
3 years ago
var blog = context.Add(
new ConcurrentBlog { Name = "One Unicorn" }).Entity;
3 years ago
context.SaveChanges();
3 years ago
using var innerContext = new BlogContextConcurrencyWithRowversion(testStore.Name);
var updatedBlog = innerContext.ConcurrentBlogs.Single();
updatedBlog.Name = "One Pegasus";
innerContext.SaveChanges();
var currentTimestamp = updatedBlog.Timestamp.ToArray();
3 years ago
try
{
blog.Name = "One Earth Pony";
context.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
// Update original values (and optionally any current values)
// Would normally do this with just one method call
context.Entry(blog).Property(e => e.Id).OriginalValue = updatedBlog.Id;
context.Entry(blog).Property(e => e.Name).OriginalValue = updatedBlog.Name;
context.Entry(blog).Property(e => e.Timestamp).OriginalValue = updatedBlog.Timestamp;
3 years ago
context.SaveChanges();
3 years ago
Assert.NotEqual(blog.Timestamp, currentTimestamp);
}
}
public class BlogContextConcurrencyWithRowversion : ContextBase
{
public BlogContextConcurrencyWithRowversion(string databaseName)
: base(databaseName)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ConcurrentBlog>()
.Property(e => e.Timestamp)
.ValueGeneratedOnAddOrUpdate()
.IsConcurrencyToken();
}
}
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedOn { get; set; }
public int? OtherId { get; set; }
}
public class NullableKeyBlog
{
public int? Id { get; set; }
public string Name { get; set; }
public DateTime CreatedOn { get; set; }
}
public class FullNameBlog
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get; set; }
}
public class GuidBlog
{
public Guid Id { get; set; }
public string Name { get; set; }
public Guid NotId { get; set; }
}
public class ConcurrentBlog
{
public int Id { get; set; }
public string Name { get; set; }
public byte[] Timestamp { get; set; }
}
public abstract class ContextBase : DbContext
{
private readonly string _databaseName;
protected ContextBase(string databaseName)
{
_databaseName = databaseName;
}
public DbSet<Blog> Blogs { get; set; }
public DbSet<NullableKeyBlog> NullableKeyBlogs { get; set; }
public DbSet<FullNameBlog> FullNameBlogs { get; set; }
public DbSet<GuidBlog> GuidBlogs { get; set; }
public DbSet<ConcurrentBlog> ConcurrentBlogs { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.EnableServiceProviderCaching(false)
.UseJet(
JetTestStore.CreateConnectionString(_databaseName),
TestEnvironment.DataAccessProviderFactory,
b => b.ApplyConfiguration());
}
}
}