Names changed, same tests as EntityFramework works (almost) the same
60af6faaefbfd3fd7121a76375513a79dcdc4fa6
15 files changed
JsonContextDb.JsonContext/DbContext.csJsonContextDb.JsonContext/DbContextOptions.csJsonContextDb.JsonContext/DbSet.csJsonContextDb.JsonContext/JsonContext.csJsonContextDb.JsonContext/JsonContextOptions.csJsonContextDb.JsonContext/JsonSet.csJsonContextDb.JsonContext/MetaData.csJsonContextDb.JsonContext/QueryableExtensions.csJsonContextDb.TestApp/EFTester.csJsonContextDb.TestApp/JCTester.csJsonContextDb.TestApp/JsonContextDb.TestApp.csprojJsonContextDb.TestApp/Program.csJsonContextDb.TestApp/Tester.csJsonContextDb.TestApp/User.csJsonContextDb.TestApp/Vser.cs
diff --git a/JsonContextDb.JsonContext/JsonContext.cs b/JsonContextDb.JsonContext/DbContext.cs
similarity index 95%
rename from JsonContextDb.JsonContext/JsonContext.cs
rename to JsonContextDb.JsonContext/DbContext.cs
index a35996c..c0a0b73 100644
--- a/JsonContextDb.JsonContext/JsonContext.cs
+++ b/JsonContextDb.JsonContext/DbContext.cs
@@ -17,13 +17,13 @@ namespace JsonContextDb.JsonContext;
/// and <see cref="SaveChangesAsync"/> for persisting changes. Entities must have an integer <c>Id</c> property.
/// Copyright (c) 2025 Alphons van der Heijden. All rights reserved.
/// </remarks>
-public class JsonContext(string? dataDirectory, JsonContextOptions? options = null)
+public class DbContext(string? dataDirectory, DbContextOptions? options = null)
{
// Directory where JSON files are stored, required and validated.
private readonly string dataDirectory = dataDirectory ?? throw new ArgumentNullException(nameof(dataDirectory));
// Configuration options for serialization and file naming.
- private readonly JsonContextOptions jsonContextOptions = options ?? new JsonContextOptions();
+ private readonly DbContextOptions jsonContextOptions = options ?? new DbContextOptions();
// In-memory storage of entity lists, keyed by entity type.
private readonly Dictionary<Type, IList> entityLists = [];
@@ -54,7 +54,7 @@ public class JsonContext(string? dataDirectory, JsonContextOptions? options = nu
/// <typeparam name="T">The type of entity, which must be a class with an integer <c>Id</c> property.</typeparam>
/// <returns>A <see cref="List{T}"/> containing the deserialized entities, or an empty list if the file does not exist.</returns>
/// <remarks>
- /// The JSON file is named using the <see cref="JsonContextOptions.FileNameFactory"/> and located in the directory
+ /// The JSON file is named using the <see cref="DbContextOptions.FileNameFactory"/> and located in the directory
/// specified during construction. If the file does not exist or is corrupted, an empty list is returned or an exception
/// is thrown. This method uses synchronous file I/O for simplicity and is called by <see cref="Set{T}"/> to initialize
/// the in-memory entity list.
@@ -101,7 +101,7 @@ public class JsonContext(string? dataDirectory, JsonContextOptions? options = nu
=> SHA256.HashData(JsonSerializer.SerializeToUtf8Bytes(entity, options)); // 32 bytes output
// Retrieves a queryable set of entities of type T
- public JsonSet<T> Set<T>() where T : class => new(this);
+ public DbSet<T> Set<T>() where T : class => new(this);
internal List<T> GetList<T>() where T : class
{
@@ -110,11 +110,11 @@ public class JsonContext(string? dataDirectory, JsonContextOptions? options = nu
return entityLists[typeof(T)] as List<T> ?? throw new Exception($"LoadEntities returned null on {nameof(T)}");
}
- private List<object> GetList(Type type)
+ private IList GetList(Type type)
{
if (!entityLists.TryGetValue(type, out IList? list))
throw new Exception($"Collection {type} disapeared");
- return [.. list.Cast<object>()];
+ return list;
}
/// <summary>
@@ -196,8 +196,8 @@ public class JsonContext(string? dataDirectory, JsonContextOptions? options = nu
ArgumentNullException.ThrowIfNull(entity);
lock (lockObject)
{
- var list = GetList<T>();
- list.Add(entity);
+ //var list = GetList<T>();
+ //list.Add(entity);
changes.Add((typeof(T), entity, ActionType.Add));
snapshots[entity] = ComputeSHA256Hash(entity, jsonContextOptions.SerializerOptions);
@@ -214,12 +214,12 @@ public class JsonContext(string? dataDirectory, JsonContextOptions? options = nu
ArgumentNullException.ThrowIfNull(entities);
lock (lockObject)
{
- var list = GetList<T>();
+ //var list = GetList<T>();
foreach (var entity in entities)
{
ArgumentNullException.ThrowIfNull(entity);
- list.Add(entity);
+ //list.Add(entity);
changes.Add((typeof(T), entity, ActionType.Add));
snapshots[entity] = ComputeSHA256Hash(entity, jsonContextOptions.SerializerOptions);
}
@@ -368,14 +368,15 @@ public class JsonContext(string? dataDirectory, JsonContextOptions? options = nu
snapshots[change.Entity] = ComputeSHA256Hash(change.Entity, jsonContextOptions.SerializerOptions);
- //entities.Add(change.Entity); // DONT
+ entities.Add(change.Entity);
+
if (typeof(MetaData) != change.Entity.GetType())
affectedEntities++;
}
else if (change.Action == ActionType.Update)
{
var id = GetId(change.Entity);
- var existing = entities.FirstOrDefault(e => GetId(e) == id);
+ var existing = entities.Cast<object>().FirstOrDefault(e => GetId(e) == id);
if (existing != null)
{
entities.Remove(existing);
@@ -386,10 +387,8 @@ public class JsonContext(string? dataDirectory, JsonContextOptions? options = nu
}
else if (change.Action == ActionType.Remove)
{
- if (entities.Remove(change.Entity))
- {
- affectedEntities++;
- }
+ entities.Remove(change.Entity);
+ affectedEntities++;
}
}
diff --git a/JsonContextDb.JsonContext/JsonContextOptions.cs b/JsonContextDb.JsonContext/DbContextOptions.cs
similarity index 77%
rename from JsonContextDb.JsonContext/JsonContextOptions.cs
rename to JsonContextDb.JsonContext/DbContextOptions.cs
index 9b670e8..fe9b6c8 100644
--- a/JsonContextDb.JsonContext/JsonContextOptions.cs
+++ b/JsonContextDb.JsonContext/DbContextOptions.cs
@@ -3,15 +3,15 @@
namespace JsonContextDb.JsonContext;
/// <summary>
-/// Configuration options for <see cref="JsonContext"/>, controlling JSON serialization and file naming.
+/// Configuration options for <see cref="DbContext"/>, controlling JSON serialization and file naming.
/// </summary>
/// <remarks>
-/// This class allows customization of how <see cref="JsonContext"/> serializes entities to JSON and names the output files.
-/// Instances of this class are typically provided during <see cref="JsonContext"/> initialization and should not be modified
+/// This class allows customization of how <see cref="DbContext"/> serializes entities to JSON and names the output files.
+/// Instances of this class are typically provided during <see cref="DbContext"/> initialization and should not be modified
/// afterward to ensure consistent behavior. The default settings enable indented JSON output and generate file names based on
/// the entity type name (e.g., "Customer.json" for a <c>Customer</c> type).
/// </remarks>
-public class JsonContextOptions
+public class DbContextOptions
{
/// <summary>
/// Gets or sets the JSON serialization options used for reading and writing entities.
@@ -19,7 +19,7 @@ public class JsonContextOptions
/// <remarks>
/// The default value is a <see cref="JsonSerializerOptions"/> instance with <c>WriteIndented</c> set to <c>true</c> for readable JSON output.
/// Customizing this property allows control over serialization behavior, such as case sensitivity or property naming.
- /// This property must not be null when used by <see cref="JsonContext"/>.
+ /// This property must not be null when used by <see cref="DbContext"/>.
/// </remarks>
/// <exception cref="ArgumentNullException">Thrown if set to null.</exception>
public JsonSerializerOptions SerializerOptions { get; set; } = new() { WriteIndented = true };
@@ -31,7 +31,7 @@ public class JsonContextOptions
/// The default factory generates file names in the format "{TypeName}.json" (e.g., "Customer.json" for a <c>Customer</c> type).
/// Customizing this function allows for alternative naming conventions, such as including subdirectories or different extensions.
/// The function must return a valid file name and should not return null or empty strings.
- /// This property must not be null when used by <see cref="JsonContext"/>.
+ /// This property must not be null when used by <see cref="DbContext"/>.
/// </remarks>
/// <exception cref="ArgumentNullException">Thrown if set to null.</exception>
public Func<Type, string> FileNameFactory { get; set; } = type => $"{type.Name}.json";
diff --git a/JsonContextDb.JsonContext/DbSet.cs b/JsonContextDb.JsonContext/DbSet.cs
new file mode 100644
index 0000000..41e78c0
--- /dev/null
+++ b/JsonContextDb.JsonContext/DbSet.cs
@@ -0,0 +1,130 @@
+using System.Collections;
+using System.Linq.Expressions;
+using System.Runtime.CompilerServices;
+
+namespace JsonContextDb.JsonContext;
+
+/// <summary>
+/// A queryable collection of entities that supports querying, adding, updating, and removing entities
+/// in a JSON-based data context.
+/// </summary>
+/// <typeparam name="T">The type of entity, which must be a class with an integer <c>Id</c> property.</typeparam>
+public class DbSet<T>(DbContext context) : IQueryable<T>, IQueryable, IEnumerable<T>, IEnumerable where T : class
+{
+ // Reference to the parent JsonContext for operations.
+ private readonly DbContext context = context ?? throw new ArgumentNullException(nameof(context));
+
+ // Queryable entity collection for LINQ operations.
+ private IQueryable<T> GetQueryable() => context.GetList<T>().AsQueryable();
+
+ /// <summary>
+ /// Gets the type of the elements in the collection.
+ /// </summary>
+ public Type ElementType => GetQueryable().ElementType;
+
+ /// <summary>
+ /// Gets the expression tree that represents the query.
+ /// </summary>
+ public Expression Expression => GetQueryable().Expression;
+
+ /// <summary>
+ /// Gets the query provider that executes the query.
+ /// </summary>
+ public IQueryProvider Provider => GetQueryable().Provider;
+
+ /// <summary>
+ /// Adds a single entity to the data context.
+ /// </summary>
+ /// <param name="entity">The entity to add.</param>
+ public void Add(T entity) => context.Add(entity);
+
+ /// <summary>
+ /// Adds a collection of entities to the data context.
+ /// </summary>
+ /// <param name="entities">The entities to add.</param>
+ public void AddRange(IEnumerable<T> entities) => context.AddRange(entities);
+
+ /// <summary>
+ /// Adds a collection of entities to the data context.
+ /// </summary>
+ /// <param name="entities">The entities to add.</param>
+ public void AddRange(params T[] entities) => context.AddRange(entities);
+
+ /// <summary>
+ /// Updates a single entity in the data context.
+ /// </summary>
+ /// <param name="entity">The entity to update.</param>
+ public void Update(T entity) => context.Update(entity);
+
+ /// <summary>
+ /// Updates a collection of entities in the data context.
+ /// </summary>
+ /// <param name="entities">The entities to update.</param>
+ public void UpdateRange(IEnumerable<T> entities) => context.UpdateRange(entities);
+
+ /// <summary>
+ /// Removes a single entity from the data context.
+ /// </summary>
+ /// <param name="entity">The entity to remove.</param>
+ public void Remove(T entity) => context.Remove(entity);
+
+ /// <summary>
+ /// Removes a collection of entities from the data context.
+ /// </summary>
+ /// <param name="entities">The entities to remove.</param>
+ public void RemoveRange(IEnumerable<T> entities) => context.RemoveRange(entities);
+
+ /// <summary>
+ /// Gets an enumerator for the collection of entities.
+ /// </summary>
+ /// <returns>An enumerator that can be used to iterate through the collection.</returns>
+ public IEnumerator<T> GetEnumerator() => GetQueryable().GetEnumerator();
+
+ /// <summary>
+ /// Gets a non-generic enumerator for the collection of entities.
+ /// </summary>
+ /// <returns>An enumerator that can be used to iterate through the collection.</returns>
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+
+ /// <summary>
+ /// Asynchronously retrieves the first entity that matches the specified predicate, or the first entity if no predicate is provided.
+ /// Returns null if no entity is found.
+ /// </summary>
+ /// <param name="predicate">An optional expression to filter entities.</param>
+ /// <returns>A task representing the asynchronous operation, returning the first matching entity or null.</returns>
+ public Task<T?> FirstOrDefaultAsync(Expression<Func<T, bool>>? predicate = null)
+ {
+ var queryable = GetQueryable();
+ var result = predicate != null
+ ? queryable.FirstOrDefault(predicate)
+ : queryable.FirstOrDefault();
+ return Task.FromResult(result);
+ }
+
+ /// <summary>
+ /// Asynchronously retrieves all entities as a list.
+ /// </summary>
+ /// <returns>A task representing the asynchronous operation, returning a list of all entities.</returns>
+ public Task<List<T>> ToListAsync()
+ {
+ var result = GetQueryable().ToList();
+ return Task.FromResult(result);
+ }
+
+ /// <summary>
+ /// Asynchronously streams entities that match the specified predicate, or all entities if no predicate is provided.
+ /// </summary>
+ /// <param name="predicate">An optional expression to filter entities.</param>
+ /// <returns>An asynchronous enumerable of entities that match the predicate.</returns>
+ public async IAsyncEnumerable<T> GetAsyncEnumerable([EnumeratorCancellation] CancellationToken cancellationToken = default, Expression<Func<T, bool>>? predicate = null)
+ {
+ var queryable = GetQueryable();
+ var enumerable = predicate != null ? queryable.Where(predicate) : queryable;
+ foreach (var entity in enumerable)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ await Task.Yield(); // Ensures asynchronous context
+ yield return entity;
+ }
+ }
+}
diff --git a/JsonContextDb.JsonContext/JsonSet.cs b/JsonContextDb.JsonContext/JsonSet.cs
deleted file mode 100644
index 3b9714d..0000000
--- a/JsonContextDb.JsonContext/JsonSet.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System.Collections;
-using System.Linq.Expressions;
-
-namespace JsonContextDb.JsonContext;
-
-/// <summary>
-/// A queryable collection of entities that supports querying, adding, updating, and removing entities
-/// in a JSON-based data context.
-/// </summary>
-/// <typeparam name="T">The type of entity, which must be a class with an integer <c>Id</c> property.</typeparam>
-public class JsonSet<T>(JsonContext context) : IQueryable<T>, IQueryable, IEnumerable<T>, IEnumerable where T : class
-{
- // Reference to the parent JsonContext for operations.
- private readonly JsonContext context = context ?? throw new ArgumentNullException(nameof(context));
-
- // Queryable entity collection for LINQ operations.
- private IQueryable<T> GetQueryable() => context.GetList<T>().AsQueryable();
- public Type ElementType => GetQueryable().ElementType;
- public Expression Expression => GetQueryable().Expression;
- public IQueryProvider Provider => GetQueryable().Provider;
- public void Add(T entity) => context.Add(entity);
- public void AddRange(IEnumerable<T> entities) => context.AddRange(entities);
- public void Update(T entity) => context.Update(entity);
- public void UpdateRange(IEnumerable<T> entities) => context.UpdateRange(entities);
- public void Remove(T entity) => context.Remove(entity);
- public void RemoveRange(IEnumerable<T> entities) => context.RemoveRange(entities);
- public IEnumerator<T> GetEnumerator() => GetQueryable().GetEnumerator();
- IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
-
- /// <summary>
- /// Asynchronously retrieves the first entity that matches the specified predicate, or the first entity if no predicate is provided.
- /// Returns null if no entity is found.
- /// </summary>
- /// <param name="predicate">An optional expression to filter entities.</param>
- /// <returns>A task representing the asynchronous operation, returning the first matching entity or null.</returns>
- public Task<T?> FirstOrDefaultAsync(Expression<Func<T, bool>>? predicate = null)
- {
- var queryable = GetQueryable();
- var result = predicate != null
- ? queryable.FirstOrDefault(predicate)
- : queryable.FirstOrDefault();
- return Task.FromResult(result);
- }
-
- /// <summary>
- /// Asynchronously retrieves all entities as a list.
- /// </summary>
- /// <returns>A task representing the asynchronous operation, returning a list of all entities.</returns>
- public Task<List<T>> ToListAsync()
- {
- var result = GetQueryable().ToList();
- return Task.FromResult(result);
- }
-}
diff --git a/JsonContextDb.JsonContext/MetaData.cs b/JsonContextDb.JsonContext/MetaData.cs
index c27096e..b20569a 100644
--- a/JsonContextDb.JsonContext/MetaData.cs
+++ b/JsonContextDb.JsonContext/MetaData.cs
@@ -1,5 +1,4 @@
-
-namespace JsonContextDb.JsonContext;
+namespace JsonContextDb.JsonContext;
internal class MetaData
{
diff --git a/JsonContextDb.JsonContext/QueryableExtensions.cs b/JsonContextDb.JsonContext/QueryableExtensions.cs
new file mode 100644
index 0000000..8e4344d
--- /dev/null
+++ b/JsonContextDb.JsonContext/QueryableExtensions.cs
@@ -0,0 +1,22 @@
+namespace JsonContextDb.JsonContext;
+
+public static class QueryableExtensions
+{
+ public static Task<List<T>> ToListAsync<T>(this IQueryable<T> queryable)
+ {
+ return queryable == null ? throw new ArgumentNullException(nameof(queryable)) : Task.FromResult(queryable.ToList());
+ }
+
+#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
+ public static async IAsyncEnumerable<T> AsAsyncEnumerable<T>(this IQueryable<T> queryable)
+#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
+ {
+ ArgumentNullException.ThrowIfNull(queryable);
+
+ foreach (var item in queryable.ToList())
+ {
+ yield return item;
+ }
+ }
+
+}
diff --git a/JsonContextDb.TestApp/EFTester.cs b/JsonContextDb.TestApp/EFTester.cs
new file mode 100644
index 0000000..bdaca96
--- /dev/null
+++ b/JsonContextDb.TestApp/EFTester.cs
@@ -0,0 +1,87 @@
+using Microsoft.EntityFrameworkCore;
+using System.Diagnostics;
+
+namespace JsonContextDb.TestApp;
+
+public class EFTester
+{
+ public static async Task Main()
+ {
+ await using var context = new EFUsersContext(
+ new DbContextOptionsBuilder<EFUsersContext>()
+ .UseInMemoryDatabase(databaseName: "UsersDb")
+ .Options);
+
+ context.Users.AddRange(
+ new User { Name = "Alphons" },
+ new User { Name = "Annet" }
+ );
+
+ Debug.Assert(context.Users.Count() == 0);
+
+ var cnt = await context.SaveChangesAsync();
+
+ var tttt = context.Users;
+
+ Debug.Assert(cnt == 2);
+
+ Debug.Assert(context.Users.Count() == 2);
+
+ var users = await context.Users
+ .Where(p => p.Name.Contains('A'))
+ .OrderBy(p => p.Name)
+ .ToListAsync();
+
+ foreach (var user in users)
+ {
+ Console.WriteLine($"Id:{user.Id} User: {user.Name}");
+ }
+
+ var alphons = await context.Users.FirstOrDefaultAsync(p => p.Name == "Alphons");
+
+ if (alphons != null)
+ {
+ alphons.Name = "Alphonsje";
+
+ var name = context.Users.ToList()[0].Name;
+
+ Debug.Assert(name == "Alphonsje");
+
+ var cnt2 = await context.SaveChangesAsync();
+
+ Debug.Assert(cnt2 == 1);
+
+ Debug.Assert(context.Users.Where(x => x.Id == 1).FirstOrDefault()?.Name == "Alphonsje");
+
+ Console.WriteLine($"\nBijgewerkte Name voor {alphons.Name}");
+ }
+
+ var alphonsDelete = await context.Users
+ .FirstOrDefaultAsync(p => p.Name == "Alphonsje");
+
+ if (alphonsDelete != null)
+ {
+ context.Users.Remove(alphonsDelete);
+
+ Debug.Assert(context.Users.Where(x => x.Id == 1).FirstOrDefault()?.Name == "Alphonsje");
+
+ var cnt3 = await context.SaveChangesAsync();
+
+ Debug.Assert(cnt3 == 1);
+
+ Console.WriteLine($"Alphonsje verwijderd {cnt3}");
+ }
+
+ Console.WriteLine("\nResterende users:");
+ await foreach (var user in context.Users.AsAsyncEnumerable())
+ {
+ Console.WriteLine($"Id:{user.Id} User: {user.Name}");
+ }
+ }
+}
+
+
+public class EFUsersContext(DbContextOptions<EFUsersContext> options) : DbContext(options)
+{
+ public DbSet<User> Users { get; set; }
+}
diff --git a/JsonContextDb.TestApp/JCTester.cs b/JsonContextDb.TestApp/JCTester.cs
new file mode 100644
index 0000000..3b2551d
--- /dev/null
+++ b/JsonContextDb.TestApp/JCTester.cs
@@ -0,0 +1,87 @@
+using JsonContextDb.JsonContext;
+using System.Diagnostics;
+
+namespace JsonContextDb.TestApp;
+
+public class JCTester
+{
+ public static async Task Main()
+ {
+ File.Delete(Path.Combine(AppContext.BaseDirectory, "Data", "User.json"));
+ File.Delete(Path.Combine(AppContext.BaseDirectory, "Data", "MetaData.json"));
+
+ var context = new JCUsersContext(Path.Combine(AppContext.BaseDirectory, "Data"));
+
+ context.Users.AddRange(
+ new User { Name = "Alphons" },
+ new User { Name = "Annet" }
+ );
+
+ Debug.Assert(context.Users.Count() == 0);
+
+ var cnt = await context.SaveChangesAsync();
+
+ var tttt = context.Users;
+
+ Debug.Assert(cnt == 2);
+
+ Debug.Assert(context.Users.Count() == 2);
+
+ var users = await context.Users
+ .Where(p => p.Name.Contains('A'))
+ .OrderBy(p => p.Name)
+ .ToListAsync();
+
+ foreach (var user in users)
+ {
+ Console.WriteLine($"Id:{user.Id} User: {user.Name}");
+ }
+
+ var alphons = await context.Users.FirstOrDefaultAsync(p => p.Name == "Alphons");
+
+ if (alphons != null)
+ {
+ alphons.Name = "Alphonsje";
+
+ var name = context.Users.ToList()[0].Name;
+
+ Debug.Assert(name == "Alphonsje");
+
+ var cnt2 = await context.SaveChangesAsync();
+
+ Debug.Assert(cnt2 == 1);
+
+ Debug.Assert(context.Users.Where(x => x.Id == 1).FirstOrDefault()?.Name == "Alphonsje");
+
+ Console.WriteLine($"\nBijgewerkte Name voor {alphons.Name}");
+ }
+
+ var alphonsDelete = await context.Users
+ .FirstOrDefaultAsync(p => p.Name == "Alphonsje");
+
+ if (alphonsDelete != null)
+ {
+ context.Users.Remove(alphonsDelete);
+
+ Debug.Assert(context.Users.Where(x => x.Id == 1).FirstOrDefault()?.Name == "Alphonsje");
+
+ var cnt3 = await context.SaveChangesAsync();
+
+ Debug.Assert(cnt3 == 1);
+
+ Console.WriteLine($"Alphonsje verwijderd {cnt3}");
+ }
+
+ Console.WriteLine("\nResterende users:");
+ await foreach (var user in context.Users.AsAsyncEnumerable())
+ {
+ Console.WriteLine($"Id:{user.Id} User: {user.Name}");
+ }
+ }
+}
+
+
+public class JCUsersContext(string dataDirectory) : DbContext(dataDirectory)
+{
+ public DbSet<User> Users => Set<User>();
+}
diff --git a/JsonContextDb.TestApp/JsonContextDb.TestApp.csproj b/JsonContextDb.TestApp/JsonContextDb.TestApp.csproj
index 30933ba..42f50ed 100644
--- a/JsonContextDb.TestApp/JsonContextDb.TestApp.csproj
+++ b/JsonContextDb.TestApp/JsonContextDb.TestApp.csproj
@@ -7,6 +7,10 @@
<Nullable>enable</Nullable>
</PropertyGroup>
+ <ItemGroup>
+ <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.15" />
+ </ItemGroup>
+
<ItemGroup>
<ProjectReference Include="..\JsonContextDb.JsonContext\JsonContextDb.JsonContext.csproj" />
</ItemGroup>
diff --git a/JsonContextDb.TestApp/Program.cs b/JsonContextDb.TestApp/Program.cs
index 592e6d2..1cbf91d 100644
--- a/JsonContextDb.TestApp/Program.cs
+++ b/JsonContextDb.TestApp/Program.cs
@@ -1,83 +1,14 @@
-using JsonContextDb.JsonContext;
-using System.Diagnostics;
-var context = new JsonContext(Path.Combine(AppContext.BaseDirectory, "Data"));
+using JsonContextDb.TestApp;
-var users = context.Set<User>();
-var vsers = context.Set<Vser>();
+//await Tester.Main();
-if (!users.Any())
-{
- var nr = 2;
- for (int i = 1; i <= nr; i++)
- {
- users.Add(new User
- {
- Name = $"annet {i}"
- });
- vsers.Add(new Vser
- {
- Name = $"alphons {i}"
- });
- }
+Console.WriteLine("---------------------------------------------");
+await EFTester.Main();
+Console.WriteLine("---------------------------------------------");
- Debug.Assert(users.Count() == nr);
- Debug.Assert(vsers.Count() == nr);
+Console.WriteLine("---------------------------------------------");
+await JCTester.Main();
+Console.WriteLine("---------------------------------------------");
- var cnt = await context.SaveChangesAsync();
-
- Debug.Assert(cnt == 2 * nr);
-}
-
-var total = users.Count();
-
-var sw = Stopwatch.StartNew();
-
-var newUser = new User
-{
- Name = "Daar gaat ie"
-};
-
-users.Add(newUser);
-
-Debug.Assert(users.Count() == total + 1);
-
-Debug.Assert(newUser.Id == 0);
-
-var count1 = await context.SaveChangesAsync();
-
-Debug.Assert(count1 == 1);
-
-Debug.Assert(newUser.Id != 0);
-
-var user = await users.FirstOrDefaultAsync(x => x.Name.Contains("1"));
-
-//Debug.Assert(user != null);
-
-//if (user != null)
-// Console.WriteLine($"{user.Name} - {user.Id} {sw.ElapsedMilliseconds} mS");
-
-//Debug.Assert(users.Count() == total + 1);
-
-newUser.Name = "Tester 1";
-
-var count = await context.SaveChangesAsync();
-
-Debug.Assert(count == 1);
-
-Console.WriteLine($"{sw.ElapsedMilliseconds} mS");
-
-Console.ReadLine();
-
-class User
-{
- public int Id { get; set; }
- public string Name { get; set; } = string.Empty;
-}
-
-class Vser
-{
- public int Id { get; set; }
- public string Name { get; set; } = string.Empty;
-}
\ No newline at end of file
diff --git a/JsonContextDb.TestApp/Tester.cs b/JsonContextDb.TestApp/Tester.cs
new file mode 100644
index 0000000..d86fd3c
--- /dev/null
+++ b/JsonContextDb.TestApp/Tester.cs
@@ -0,0 +1,110 @@
+
+using JsonContextDb.JsonContext;
+using System.Diagnostics;
+
+namespace JsonContextDb.TestApp;
+
+internal class Tester
+{
+ public static async Task Main()
+ {
+ var context = new DbContext(Path.Combine(AppContext.BaseDirectory, "Data"));
+
+ var users = context.Set<User>();
+ var vsers = context.Set<Vser>();
+
+ if (!users.Any())
+ {
+ var nr = 2;
+ for (int i = 1; i <= nr; i++)
+ {
+ users.Add(new User
+ {
+ Name = $"annet {i}"
+ });
+ vsers.Add(new Vser
+ {
+ Name = $"alphons {i}"
+ });
+ }
+
+ Debug.Assert(users.Count() == nr);
+ Debug.Assert(vsers.Count() == nr);
+
+ var cnt9 = await context.SaveChangesAsync();
+
+ Debug.Assert(cnt9 == 2 * nr);
+ }
+
+ users.Add(new User
+ {
+ Name = $"Test1"
+ });
+ users.Add(new User
+ {
+ Name = $"Test2"
+ });
+ users.Add(new User
+ {
+ Name = $"Test3"
+ });
+ var cnt = await context.SaveChangesAsync();
+
+ var uremove = await users.FirstOrDefaultAsync(x => x.Name == "Test2");
+
+ if (uremove != null)
+ {
+ users.Remove(uremove);
+
+ var cnt3 = users.Count();
+
+ var cnt4 = await context.SaveChangesAsync();
+
+ var cnt5 = users.Count();
+ }
+
+
+
+
+ var total = users.Count();
+
+ var sw = Stopwatch.StartNew();
+
+ var newUser = new User
+ {
+ Name = "Daar gaat ie"
+ };
+
+ users.Add(newUser);
+
+ Debug.Assert(users.Count() == total + 1);
+
+ Debug.Assert(newUser.Id == 0);
+
+ var count1 = await context.SaveChangesAsync();
+
+ Debug.Assert(count1 == 1);
+
+ Debug.Assert(newUser.Id != 0);
+
+ var user = await users.FirstOrDefaultAsync(x => x.Name.Contains("1"));
+
+ Debug.Assert(user != null);
+
+ if (user != null)
+ Console.WriteLine($"{user.Name} - {user.Id} {sw.ElapsedMilliseconds} mS");
+
+ Debug.Assert(users.Count() == total + 1);
+
+ newUser.Name = "Tester 1";
+
+ var count = await context.SaveChangesAsync();
+
+ Debug.Assert(count == 1);
+
+ Console.WriteLine($"{sw.ElapsedMilliseconds} mS");
+
+ Console.ReadLine();
+ }
+
+}
diff --git a/JsonContextDb.TestApp/User.cs b/JsonContextDb.TestApp/User.cs
new file mode 100644
index 0000000..8b579e0
--- /dev/null
+++ b/JsonContextDb.TestApp/User.cs
@@ -0,0 +1,8 @@
+
+namespace JsonContextDb.TestApp;
+
+public class User
+{
+ public int Id { get; set; }
+ public string Name { get; set; } = string.Empty;
+}
diff --git a/JsonContextDb.TestApp/Vser.cs b/JsonContextDb.TestApp/Vser.cs
new file mode 100644
index 0000000..743bcfd
--- /dev/null
+++ b/JsonContextDb.TestApp/Vser.cs
@@ -0,0 +1,9 @@
+
+
+namespace JsonContextDb.TestApp;
+
+public class Vser
+{
+ public int Id { get; set; }
+ public string Name { get; set; } = string.Empty;
+}