Переглянути джерело

fix up infrastructure UOW, add general tests

Dalibor Votruba 3 роки тому
батько
коміт
9324bef2ce
28 змінених файлів з 415 додано та 36 видалено
  1. 3 3
      Common/qdr.fnd.core.data.itfc/Domain/IDomain.cs
  2. 3 0
      Common/qdr.fnd.core.data.itfc/Domain/IUnitOfWork.cs
  3. 0 1
      Common/qdr.fnd.core.data.itfc/Repository/IRepository.cs
  4. 24 1
      Common/qdr.fnd.core.data/Domain/DataDomain.cs
  5. 9 0
      Common/qdr.fnd.core.data/Domain/IDataDomain.cs
  6. 12 0
      Common/qdr.fnd.core.data/Domain/UnitOfWork.cs
  7. 6 8
      Common/qdr.fnd.core.data/Repository/EntityRepository.cs
  8. 16 0
      Common/qdr.fnd.core.test/Repositories/Fakes/TestDao.cs
  9. 23 0
      Common/qdr.fnd.core.test/Repositories/Fakes/TestDbContext.cs
  10. 13 0
      Common/qdr.fnd.core.test/Repositories/Fakes/TestRepo.cs
  11. 207 0
      Common/qdr.fnd.core.test/Repositories/GeneralRepositoryTest.cs
  12. 5 2
      Common/qdr.fnd.core.test/ServiceDbContextTest.cs
  13. 1 0
      Common/qdr.fnd.core.test/qdr.fnd.core.test.csproj
  14. 1 1
      Common/qdr.fnd.core/Json/Binder.cs
  15. 1 1
      Common/qdr.fnd.core/Reflection/Extensions/AssemblyExt.cs
  16. 1 1
      Common/qdr.fnd.core/Thread/AbstractWorker.cs
  17. 1 4
      Common/qdr.fnd.core/Value/Extensions/TimeSpanExt.cs
  18. 4 3
      Modules/qdr.app.qlbrc.base/QlbrcDbContext.cs
  19. 1 1
      Modules/qdr.app.qlbrc.base/Repositories/RepoSetting.cs
  20. 1 1
      Modules/qdr.app.qlbrc.base/Repositories/RepoTenant.cs
  21. 1 1
      Modules/qdr.app.qlbrc.base/Repositories/RepoUser.cs
  22. 4 4
      Modules/qdr.app.qlbrc.base/Services/SettingsService.cs
  23. 14 0
      Tests/qdr.app.qlbrc.base.Tests/BaseInMemoryDbContext.cs
  24. 43 0
      Tests/qdr.app.qlbrc.base.Tests/Services/SettingsServiceTest.cs
  25. 7 0
      Tests/qdr.app.qlbrc.base.Tests/qdr.app.qlbrc.base.Tests.csproj
  26. 12 0
      Tests/qdr.app.qlbrc.base.Tests/qlbrc.test.json
  27. 1 0
      Tests/qdr.app.qlbrc.common.Tests/qdr.app.qlbrc.common.Tests.csproj
  28. 1 4
      qdr.app.qlbrc.sln

+ 3 - 3
Common/qdr.fnd.core.data.itfc/Domain/IDomain.cs

@@ -2,8 +2,8 @@
 {
     public interface IDomain
     {
-        TEntitySet GetDbSet<TEntitySet>();
-        IUnitOfWork<TDomainContext> CreateUnitOfWork<TDomainContext>() where TDomainContext : IDomain;
-        void Commit();
+        public IUnitOfWork<TDomainContext> CreateUnitOfWork<TDomainContext>() where TDomainContext : IDomain;
+        public void Commit();
+        public void Rollback();
     }
 }

+ 3 - 0
Common/qdr.fnd.core.data.itfc/Domain/IUnitOfWork.cs

@@ -6,5 +6,8 @@ namespace Quadarax.Foundation.Core.Data.Interface.Domain
     {
         TDomainContext Context { get;  }
         void Commit();
+
+        IUnitOfWork<TCustomDomainContext> As<TCustomDomainContext>() where TCustomDomainContext : IDomain;
+
     }
 }

+ 0 - 1
Common/qdr.fnd.core.data.itfc/Repository/IRepository.cs

@@ -4,6 +4,5 @@ namespace Quadarax.Foundation.Core.Data.Interface.Repository
 {
     public interface IRepository
     {
-        void Commit();
     }
 }

+ 24 - 1
Common/qdr.fnd.core.data/Domain/DataDomain.cs

@@ -6,7 +6,7 @@ using Quadarax.Foundation.Core.Data.Interface.Domain;
 
 namespace Quadarax.Foundation.Core.Data.Domain
 {
-    public abstract class DataDomain : DbContext, IDomain
+    public abstract class DataDomain : DbContext, IDataDomain
     {
         private MethodInfo _mtSet;
         private MethodInfo _mtgSet;
@@ -36,5 +36,28 @@ namespace Quadarax.Foundation.Core.Data.Domain
         {
             this.SaveChanges();
         }
+
+        public void Rollback()
+        {
+            var changedEntries = ChangeTracker.Entries()
+                .Where(x => x.State != EntityState.Unchanged).ToList();
+
+            foreach (var entry in changedEntries)
+            {
+                switch(entry.State)
+                {
+                    case EntityState.Modified:
+                        entry.CurrentValues.SetValues(entry.OriginalValues);
+                        entry.State = EntityState.Unchanged;
+                        break;
+                    case EntityState.Added:
+                        entry.State = EntityState.Detached;
+                        break;
+                    case EntityState.Deleted:
+                        entry.State = EntityState.Unchanged;
+                        break;
+                }
+            }
+        }
     }     
 }

+ 9 - 0
Common/qdr.fnd.core.data/Domain/IDataDomain.cs

@@ -0,0 +1,9 @@
+using Quadarax.Foundation.Core.Data.Interface.Domain;
+
+namespace Quadarax.Foundation.Core.Data.Domain;
+
+public interface IDataDomain : IDomain
+{
+    TEntitySet GetDbSet<TEntitySet>();
+
+}

+ 12 - 0
Common/qdr.fnd.core.data/Domain/UnitOfWork.cs

@@ -13,14 +13,26 @@ namespace Quadarax.Foundation.Core.Data.Domain
             Context = context.GetCurrent<TDomainContext>();
         }
 
+        public UnitOfWork(TDomainContext context)
+        {
+            Context = context;
+        }
+
         public void Commit()
         {
             Context.Commit();
         }
 
+        public IUnitOfWork<TCustomDomainContext> As<TCustomDomainContext>() where TCustomDomainContext : IDomain
+        {
+            return new UnitOfWork<TCustomDomainContext>((TCustomDomainContext)(IDomain)Context);
+        }
+
         protected override void OnDisposing()
         {
+            Context?.Rollback();
             Context = default;
         }
+
     }
 }

+ 6 - 8
Common/qdr.fnd.core.data/Repository/EntityRepository.cs

@@ -16,13 +16,13 @@ namespace Quadarax.Foundation.Core.Data.Repository
         where TEntity : Entity<TKey>, new() 
         where TKey : IEquatable<TKey>
     {
-        private IUnitOfWork<DataDomain> _unitOfWork;
+        private IUnitOfWork<IDataDomain> _unitOfWork;
         private DbSet<TEntity> DbSetInstance => _unitOfWork.Context.GetDbSet<DbSet<TEntity>>();
-        protected DataDomain Context => _unitOfWork.Context;
+        protected IDataDomain Context => _unitOfWork.Context;
         
         protected IList<string> DefaultIncludes { get; }
 
-        protected EntityRepository(IUnitOfWork<DataDomain> unitOfWork)
+        protected EntityRepository(IUnitOfWork<IDataDomain> unitOfWork)
         {
             _unitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
             DefaultIncludes = new List<string>();
@@ -68,7 +68,9 @@ namespace Quadarax.Foundation.Core.Data.Repository
 
         public virtual bool Remove(TKey id)
         {
-            DbSetInstance.Remove(Get(id));
+            var dao = Get(id);
+            if (dao == null) return false;
+            DbSetInstance.Remove(dao);
             return true;
         }
 
@@ -88,9 +90,5 @@ namespace Quadarax.Foundation.Core.Data.Repository
             return entities.Select(Remove).ToList();
         }
 
-        public void Commit()
-        {
-            _unitOfWork.Commit();
-        }
     }
 }

+ 16 - 0
Common/qdr.fnd.core.test/Repositories/Fakes/TestDao.cs

@@ -0,0 +1,16 @@
+using System.ComponentModel.DataAnnotations;
+using Quadarax.Foundation.Core.Data.Entity;
+
+namespace qdr.fnd.core.test.Repositories.Fakes
+{
+    public class TestDao : Entity<long>
+    {
+        [Required]
+        [MaxLength(100)]
+        public string Name { get; set; } = null!;
+
+        [Required]
+        [MaxLength(100)]
+        public string Value { get; set; } = null!;
+    }
+}

+ 23 - 0
Common/qdr.fnd.core.test/Repositories/Fakes/TestDbContext.cs

@@ -0,0 +1,23 @@
+using System.Diagnostics;
+using Microsoft.EntityFrameworkCore;
+using Quadarax.Foundation.Core.Data.Domain;
+
+namespace qdr.fnd.core.test.Repositories.Fakes
+{
+    public class TestDbContext : DataDomain, IDataDomain
+    {
+        public DbSet<TestDao> Daos { get; set; } = null!;
+
+        public TestDbContext(DbContextOptions options) : base(options)
+        {
+        }
+
+        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+        {
+            var dbName = "test" + DateTime.Now.ToFileTime().ToString();
+            optionsBuilder.UseInMemoryDatabase(dbName)
+                .LogTo(message => Debug.WriteLine("EFSQL>>" + message));
+            Debug.WriteLine($"*** Context created [{dbName}]");
+        }
+    }
+}

+ 13 - 0
Common/qdr.fnd.core.test/Repositories/Fakes/TestRepo.cs

@@ -0,0 +1,13 @@
+using Quadarax.Foundation.Core.Data.Repository;
+using Quadarax.Foundation.Core.Data.Domain;
+using Quadarax.Foundation.Core.Data.Interface.Domain;
+
+namespace qdr.fnd.core.test.Repositories.Fakes
+{
+    public class TestRepo : EntityRepository<long, TestDao>
+    {
+        public TestRepo(IUnitOfWork<IDataDomain> unitOfWork) : base(unitOfWork)
+        {
+        }
+    }
+}

+ 207 - 0
Common/qdr.fnd.core.test/Repositories/GeneralRepositoryTest.cs

@@ -0,0 +1,207 @@
+using Microsoft.EntityFrameworkCore;
+using qdr.fnd.core.test.Repositories.Fakes;
+using Quadarax.Foundation.Core.Data;
+using Quadarax.Foundation.Core.Data.Domain;
+
+namespace qdr.fnd.core.test.Repositories
+{
+
+    [TestFixture(Category = "Dao")]
+    internal class GeneralRepositoryTest : DbContextTest
+    {
+        private DomainContextResolver<TestDbContext>? _dbcResolver;
+
+
+        private const string DaoName1 = "Name1";
+        private const string DaoName2 = "Name2";
+        private const string DaoValue1 = "Value1";
+        private const string DaoValue2 = "Value2";
+
+
+        [SetUp]
+        public void Setup()
+        {
+            var context = new TestDbContext(new DbContextOptions<TestDbContext>());
+            context.Database.EnsureCreated();
+            _dbcResolver = new DomainContextResolver<TestDbContext>(context);
+        }
+        [TearDown]
+        public void TearDown()
+        {
+            _dbcResolver?.GetCurrent<TestDbContext>().Dispose();
+            _dbcResolver = null;
+        }
+        
+        [Test]
+        public void AddEntity()
+        {
+
+            using (var uow = new UnitOfWork<TestDbContext>(_dbcResolver))
+            {
+                var repo = new TestRepo(uow.As<IDataDomain>());
+                var dao = repo.New();
+                dao.Name = DaoName1;
+                dao.Value = DaoValue1;
+                uow.Commit();
+
+                // read check inside UOW
+                dao = repo.Get(1);
+                Assert.IsNotNull(dao, "Cannot obtain created dao inside UOW.");
+                Assert.That(dao.Name, Is.EqualTo(DaoName1));
+                Assert.That(dao.Value, Is.EqualTo(DaoValue1));
+            }
+            // read check outside UOW
+            using (var uow = new UnitOfWork<TestDbContext>(_dbcResolver))
+            {
+                var repo = new TestRepo(uow.As<IDataDomain>());
+                var dao = repo.Get(1);
+                Assert.IsNotNull(dao, "Cannot obtain created dao outside UOW.");
+                Assert.That(dao.Name, Is.EqualTo(DaoName1));
+                Assert.That(dao.Value, Is.EqualTo(DaoValue1));
+            }
+        }
+
+        [Test]
+        public void UpdateEntity()
+        {
+            
+
+            using (var uow = new UnitOfWork<TestDbContext>(_dbcResolver))
+            {
+                var repo = new TestRepo(uow.As<IDataDomain>());
+                var dao = repo.New();
+                dao.Name = DaoName1;
+                dao.Value = DaoValue1;
+                uow.Commit();
+
+                dao.Value = DaoValue2;
+                uow.Commit();
+            }
+            // read check outside UOW
+            using (var uow = new UnitOfWork<TestDbContext>(_dbcResolver))
+            {
+                var repo = new TestRepo(uow.As<IDataDomain>());
+                var dao = repo.Get(1);
+                Assert.IsNotNull(dao, "Cannot obtain created dao outside UOW.");
+                Assert.That(dao.Name, Is.EqualTo(DaoName1));
+                Assert.That(dao.Value, Is.EqualTo(DaoValue2));
+            }
+        }
+        [Test]
+        public void RemoveEntity()
+        {
+            
+            var result = false;
+            using (var uow = new UnitOfWork<TestDbContext>(_dbcResolver))
+            {
+                var repo = new TestRepo(uow.As<IDataDomain>());
+                var dao = repo.New();
+                dao.Name = DaoName1;
+                dao.Value = DaoValue1;
+                uow.Commit();
+                result = repo.Remove(1);
+                uow.Commit();
+
+            }
+            // read check outside UOW
+            using (var uow = new UnitOfWork<TestDbContext>(_dbcResolver))
+            {
+                var repo = new TestRepo(uow.As<IDataDomain>());
+                var dao = repo.Get(1);
+                Assert.IsNull(dao, "Dao doesn't remove outside UOW.");
+                result = repo.Remove(1);
+                Assert.IsFalse(result);
+            }
+        }
+        [Test]
+        public void QueryEntity()
+        {
+            var context = new TestDbContext(new DbContextOptions<TestDbContext>());
+            context.Database.EnsureCreated();
+            var dbcResolver = new DomainContextResolver<TestDbContext>(context);
+
+            var result = false;
+            using (var uow = new UnitOfWork<TestDbContext>(_dbcResolver))
+            {
+                var repo = new TestRepo(uow.As<IDataDomain>());
+                var dao = repo.New();
+                dao.Name = DaoName1;
+                dao.Value = DaoValue1;
+                dao = repo.New();
+                dao.Name = DaoName2;
+                dao.Value = DaoValue2;
+                uow.Commit();
+                // read check inside UOW
+                var list = repo.Query(Paging.NoPaging());
+                Assert.IsNotNull(list);
+                Assert.That(list.Count(), Is.EqualTo(2));
+
+            }
+            // read check outside UOW
+            using (var uow = new UnitOfWork<TestDbContext>(_dbcResolver))
+            {
+                var repo = new TestRepo(uow.As<IDataDomain>());
+                var list = repo.Query(Paging.NoPaging());
+                Assert.IsNotNull(list);
+                Assert.That(list.Count(), Is.EqualTo(2));
+            }
+        }
+        [Test]
+        public void QueryPagingEntity()
+        {
+            
+            var result = false;
+            using (var uow = new UnitOfWork<TestDbContext>(_dbcResolver))
+            {
+                var repo = new TestRepo(uow.As<IDataDomain>());
+                var dao = repo.New();
+                dao.Name = DaoName1;
+                dao.Value = DaoValue1;
+                dao = repo.New();
+                dao.Name = DaoName2;
+                dao.Value = DaoValue2;
+                uow.Commit();
+
+            }
+            // read check outside UOW
+            using (var uow = new UnitOfWork<TestDbContext>(_dbcResolver))
+            {
+                var repo = new TestRepo(uow.As<IDataDomain>());
+                var list = repo.Query(new Paging(0,1))?.ToArray();
+                Assert.IsNotNull(list);
+                Assert.That(list.Count(), Is.EqualTo(1));
+                Assert.That(list[0].Name, Is.EqualTo(DaoName1));
+                list = repo.Query(new Paging(1,1))?.ToArray();
+                Assert.IsNotNull(list);
+                Assert.That(list[0].Name, Is.EqualTo(DaoName2));
+            }
+        }
+        [Test]
+        public void RollbackEntity()
+        {
+            
+            using (var uow = new UnitOfWork<TestDbContext>(_dbcResolver))
+            {
+                var repo = new TestRepo(uow.As<IDataDomain>());
+                var dao = repo.New();
+                dao.Name = DaoName1;
+                dao.Value = DaoValue1;
+                uow.Commit();
+                dao = repo.Get(1);
+                Assert.IsNotNull(dao);
+                Assert.That(dao.Name, Is.EqualTo(DaoName1));
+                dao.Name = DaoName2;
+            }
+            // read check outside UOW
+            using (var uow = new UnitOfWork<TestDbContext>(_dbcResolver))
+            {
+                var repo = new TestRepo(uow.As<IDataDomain>());
+                var dao = repo.Get(1);
+                Assert.IsNotNull(dao);
+                Assert.That(dao.Name, Is.EqualTo(DaoName1));
+
+            }
+        }
+
+    }
+}

+ 5 - 2
Common/qdr.fnd.core.test/ServiceDbContextTest.cs

@@ -1,6 +1,9 @@
-namespace qdr.fnd.core.test
+using Microsoft.EntityFrameworkCore;
+
+namespace qdr.fnd.core.test
 {
-    public abstract class ServiceDbContextTest : ServiceTest
+    public abstract class ServiceDbContextTest<TDbContext> : ServiceTest where TDbContext : DbContext
     {
+
     }
 }

+ 1 - 0
Common/qdr.fnd.core.test/qdr.fnd.core.test.csproj

@@ -9,6 +9,7 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.10" />
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
     <PackageReference Include="NUnit" Version="3.13.3" />
     <PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />

+ 1 - 1
Common/qdr.fnd.core/Json/Binder.cs

@@ -28,12 +28,12 @@ namespace Quadarax.Foundation.Core.Json
             _fileSystem = fileSystemAbstraction ?? throw new ArgumentNullException(nameof(fileSystemAbstraction));
             var jsonOpt = new JsonSerializerOptions
             {
-                IgnoreNullValues = isIgnoringNullValues,
                 WriteIndented = isPrettyPrint,
                 PropertyNameCaseInsensitive = true,
                 PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                 MaxDepth = maxDepth
             };
+            jsonOpt.IgnoreNullValues = isIgnoringNullValues;
             jsonOpt.Converters.Add(new JsonStringEnumConverter());
             SerializerOptions = jsonOpt;
         }

+ 1 - 1
Common/qdr.fnd.core/Reflection/Extensions/AssemblyExt.cs

@@ -56,7 +56,7 @@ namespace Quadarax.Foundation.Core.Reflection.Extensions
         }
         public static string GetAssemblyPath(this Assembly oAssembly)
         {
-            return Path.GetDirectoryName(new Uri(oAssembly.CodeBase).LocalPath) + Path.DirectorySeparatorChar;
+            return Path.GetDirectoryName(new Uri(oAssembly.Location).LocalPath) + Path.DirectorySeparatorChar;
         }
         public static IEnumerable<Type> GetTypesWithAttribute<TAttribute>(this Assembly oAssembly, bool bInherit)where TAttribute : System.Attribute
         {

+ 1 - 1
Common/qdr.fnd.core/Thread/AbstractWorker.cs

@@ -121,7 +121,7 @@ namespace Quadarax.Foundation.Core.Thread
         #endregion
 
         #region *** Private Operations ***
-        private async void DoInternal(object? context)
+        private async void DoInternal(object context)
         {
             var wk = (AbstractWorker)context;
             if (wk._delay != TimeSpan.Zero)

+ 1 - 4
Common/qdr.fnd.core/Value/Extensions/TimeSpanExt.cs

@@ -9,9 +9,6 @@ namespace Quadarax.Foundation.Core.Value.Extensions
     {
         public static string ToReadableString(this TimeSpan owner)
         {
-            if (owner == null)
-                throw new ArgumentNullException(nameof(owner));
-
             // formats and its cutoffs based on TotalSeconds
             var cutoff = new SortedList<long, string> { 
                 {59, "{3:S}" }, 
@@ -20,7 +17,7 @@ namespace Quadarax.Foundation.Core.Value.Extensions
                 {60*60, "{1:H}"},
                 {24*60*60-1, "{1:H}, {2:M}"},
                 {24*60*60, "{0:D}"},
-                {Int64.MaxValue , "{0:D}, {1:H}"}
+                {long.MaxValue , "{0:D}, {1:H}"}
             };
 
             // find nearest best match

+ 4 - 3
Modules/qdr.app.qlbrc.base/QlbrcDbContext.cs

@@ -2,12 +2,13 @@
 using Quadarax.Application.QLiberace.Base.Entities;
 using Quadarax.Application.QLiberace.Common.Attributes;
 using Quadarax.Application.QLiberace.Common.Configuration;
+using Quadarax.Foundation.Core.Data.Domain;
 using Quadarax.Foundation.Core.Reflection;
 
 namespace Quadarax.Application.QLiberace.Base
 {
     [DbContextModuleAssignment(Constants.Modules.Base.Code)]
-    public class QlbrcDbContext : DbContext
+    public class QlbrcDbContext : DataDomain
     {
 
         #region *** Mapped entities ***
@@ -18,7 +19,7 @@ namespace Quadarax.Application.QLiberace.Base
         #endregion
         
         #region *** Constructors ***
-        public QlbrcDbContext() : base()
+        public QlbrcDbContext() : base(new DbContextOptions<QlbrcDbContext>())
         {
         }
         public QlbrcDbContext(DbContextOptions options) : base(options)
@@ -32,7 +33,7 @@ namespace Quadarax.Application.QLiberace.Base
             optionsBuilder.UseSqlServer(GetConnectionString());
         }
 
-        private string GetConnectionString()
+        protected string GetConnectionString()
         {
             var attr = AttributeQuery<DbContextModuleAssignmentAttribute>.Get(typeof(QlbrcDbContext));
             if (attr == null)

+ 1 - 1
Modules/qdr.app.qlbrc.base/Repositories/RepoSetting.cs

@@ -9,7 +9,7 @@ namespace Quadarax.Application.QLiberace.Base.Repositories
 {
     public class RepoSetting : EntityRepository<long, Setting>
     {
-        public RepoSetting(IUnitOfWork<DataDomain> unitOfWork) : base(unitOfWork)
+        public RepoSetting(IUnitOfWork<IDataDomain> unitOfWork) : base(unitOfWork)
         {
             
         }

+ 1 - 1
Modules/qdr.app.qlbrc.base/Repositories/RepoTenant.cs

@@ -7,7 +7,7 @@ namespace Quadarax.Application.QLiberace.Base.Repositories
 {
     public class RepoTenant: EntityRepository<long, Tenant>
     {
-        public RepoTenant(IUnitOfWork<DataDomain> unitOfWork) : base(unitOfWork)
+        public RepoTenant(IUnitOfWork<IDataDomain> unitOfWork) : base(unitOfWork)
         {
         }
     }

+ 1 - 1
Modules/qdr.app.qlbrc.base/Repositories/RepoUser.cs

@@ -7,7 +7,7 @@ namespace Quadarax.Application.QLiberace.Base.Repositories
 {
     public class RepoUser : EntityRepository<long, User>
     {
-        public RepoUser(IUnitOfWork<DataDomain> unitOfWork) : base(unitOfWork)
+        public RepoUser(IUnitOfWork<IDataDomain> unitOfWork) : base(unitOfWork)
         {
         }
     }

+ 4 - 4
Modules/qdr.app.qlbrc.base/Services/SettingsService.cs

@@ -53,7 +53,7 @@ namespace Quadarax.Application.QLiberace.Base.Services
                     Repository.Set(setting);
                 }
 
-                Repository.Commit();
+                //Repository.Commit();
                 return new ResultPlain();
             });
         }
@@ -139,7 +139,7 @@ namespace Quadarax.Application.QLiberace.Base.Services
                 settings.Description = valueDescription;
                 settings.Value = value?.ToString();
                 settings.IsEnabled = true;
-                Repository.Commit();
+                //Repository.Commit();
                 return new ResultPlain();
             });
         }
@@ -169,7 +169,7 @@ namespace Quadarax.Application.QLiberace.Base.Services
                     Repository.Set(setting);
                 }
 
-                Repository.Commit();
+                //Repository.Commit();
                 return new ResultPlain();
             });
         }
@@ -192,7 +192,7 @@ namespace Quadarax.Application.QLiberace.Base.Services
                     throw ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.SettingsNotFoundCode, valueCode, moduleCode);
 
                 settings.Value = value?.ToString();
-                Repository.Commit();
+                //Repository.Commit();
                 
                 return new ResultPlain();
             });

+ 14 - 0
Tests/qdr.app.qlbrc.base.Tests/BaseInMemoryDbContext.cs

@@ -0,0 +1,14 @@
+using Microsoft.EntityFrameworkCore;
+using System.Diagnostics;
+
+namespace Quadarax.Application.QLiberace.Base.Tests
+{
+    internal class BaseInMemoryDbContext : QlbrcDbContext
+    {
+        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+        {
+            optionsBuilder.UseInMemoryDatabase(GetConnectionString())
+                .LogTo(message => Debug.WriteLine("EFSQL>>" + message));
+        }
+    }
+}

+ 43 - 0
Tests/qdr.app.qlbrc.base.Tests/Services/SettingsServiceTest.cs

@@ -0,0 +1,43 @@
+using Quadarax.Application.QLiberace.Base.Repositories;
+using Quadarax.Application.QLiberace.Common.Configuration;
+using Quadarax.Foundation.Core.Data;
+using Quadarax.Foundation.Core.Data.Domain;
+using Quadarax.Foundation.Core.Data.Interface.Domain;
+
+namespace Quadarax.Application.QLiberace.Base.Tests.Services
+{
+    [TestFixture(Category = "Srv")]
+    public class SettingsServiceTest
+    {
+        private const string CfgFileName = "qlbrc.test.json";
+
+        private IUnitOfWork<BaseInMemoryDbContext> _uow;
+
+        [SetUp]
+        public void Setup()
+        {
+            OlbrcConfiguration.ConfigurationFileName = CfgFileName;
+            var context = new BaseInMemoryDbContext();
+            context.Database.EnsureCreated();
+
+             var doc = (IDomainContextResolver<BaseInMemoryDbContext>)new DomainContextResolver<BaseInMemoryDbContext>(context);
+             _uow = new UnitOfWork<BaseInMemoryDbContext>(doc);
+        }
+
+        [Test]
+        public void TestMe()
+        {
+            var repo = new RepoSetting(_uow.As<IDataDomain>());
+            var newItem = repo.New();
+            newItem.Code = "foo";
+            newItem.ValueTypeQualified = "System.String";
+            newItem.Description = "Test";
+            newItem.ModuleCode = "Base";
+            newItem.Value = "bar";
+            repo.Set(newItem);
+            _uow.Commit();
+            var fii = repo.Query(Paging.NoPaging(),false).ToArray();
+        }
+
+    }
+}

+ 7 - 0
Tests/qdr.app.qlbrc.base.Tests/qdr.app.qlbrc.base.Tests.csproj

@@ -11,6 +11,7 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.10" />
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
     <PackageReference Include="NUnit" Version="3.13.3" />
     <PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
@@ -28,4 +29,10 @@
     <ProjectReference Include="..\..\Modules\qdr.app.qlbrc.base\qdr.app.qlbrc.base.csproj" />
   </ItemGroup>
 
+  <ItemGroup>
+    <None Update="qlbrc.test.json">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
+  </ItemGroup>
+
 </Project>

+ 12 - 0
Tests/qdr.app.qlbrc.base.Tests/qlbrc.test.json

@@ -0,0 +1,12 @@
+{
+  "modules": [
+    {
+      "code": "base",
+      "connection-string": "Initial Catalog=QLiberace;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False"
+    },
+    {
+      "code": "mod2",
+      "connection-string": "csMod2"
+    }
+  ]
+}

+ 1 - 0
Tests/qdr.app.qlbrc.common.Tests/qdr.app.qlbrc.common.Tests.csproj

@@ -11,6 +11,7 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.10" />
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" />
     <PackageReference Include="NUnit" Version="3.13.3" />
     <PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />

+ 1 - 4
qdr.app.qlbrc.sln

@@ -29,15 +29,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "qdr.app.qlbrc.base", "Modul
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "qdr.app.qlbrc.console", "qdr.app.qlbrc.console\qdr.app.qlbrc.console.csproj", "{FE8DC617-AEE2-47A1-BB50-96643A7FDAB3}"
 EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{6B02BEE0-E272-4AD5-B61D-69713331842B}"
-EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D8C71782-99B7-49FA-BF63-F40D8232B8DE}"
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "qdr.app.qlbrc.common.Tests", "Tests\qdr.app.qlbrc.common.Tests\qdr.app.qlbrc.common.Tests.csproj", "{653F7A49-07B8-4AE5-80FC-E559F38718CF}"
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "qdr.app.qlbrc.base.Tests", "Tests\qdr.app.qlbrc.base.Tests\qdr.app.qlbrc.base.Tests.csproj", "{3F99AB71-EB24-47D4-BBB6-755ED785D0FE}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "qdr.fnd.core.test", "Common\qdr.fnd.core.test\qdr.fnd.core.test.csproj", "{0D88D15B-DC73-43F2-8661-ECAAF8EEB173}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "qdr.fnd.core.test", "Common\qdr.fnd.core.test\qdr.fnd.core.test.csproj", "{0D88D15B-DC73-43F2-8661-ECAAF8EEB173}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -112,7 +110,6 @@ Global
 		{401639F1-78C2-45D5-96B9-ED2562A3D941} = {F528683A-B908-440C-9D94-F4675A3F760E}
 		{235C1F9C-CFBA-4CB0-B9A0-CCFD83D42D2F} = {F528683A-B908-440C-9D94-F4675A3F760E}
 		{6B994E28-1619-4180-BE7C-8E9DA895781E} = {24170366-2A73-4C1E-86D6-DA3C987D304E}
-		{6B02BEE0-E272-4AD5-B61D-69713331842B} = {24170366-2A73-4C1E-86D6-DA3C987D304E}
 		{D8C71782-99B7-49FA-BF63-F40D8232B8DE} = {52B118CE-E47C-475C-8177-FC49F0FC8FE8}
 		{653F7A49-07B8-4AE5-80FC-E559F38718CF} = {D8C71782-99B7-49FA-BF63-F40D8232B8DE}
 		{3F99AB71-EB24-47D4-BBB6-755ED785D0FE} = {D8C71782-99B7-49FA-BF63-F40D8232B8DE}