Merge pull request #2 from PoweredSoft/feature/ef63

Feature/ef63
This commit is contained in:
dlebee 2019-11-21 18:56:27 -06:00 committed by GitHub
commit 96ef292195
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 105 additions and 603 deletions

View File

@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio Version 16
VisualStudioVersion = 15.0.28010.2046 VisualStudioVersion = 16.0.29503.13
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PoweredSoft.Data.Core", "PoweredSoft.Data.Core\PoweredSoft.Data.Core.csproj", "{6C61F343-9634-40CD-AFC1-7C4C3FB4E524}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PoweredSoft.Data.Core", "PoweredSoft.Data.Core\PoweredSoft.Data.Core.csproj", "{6C61F343-9634-40CD-AFC1-7C4C3FB4E524}"
EndProject EndProject
@ -13,11 +13,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
README.md = README.md README.md = README.md
EndProjectSection EndProjectSection
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PoweredSoft.Data.EntityFrameworkCore.Test", "PoweredSoft.Data.EntityFrameworkCore.Test\PoweredSoft.Data.EntityFrameworkCore.Test.csproj", "{1F0B95F6-2E97-4FC2-A452-F8A071CBEF4B}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PoweredSoft.Data", "PoweredSoft.Data\PoweredSoft.Data.csproj", "{62DDEA81-6B09-4116-A91B-81FE66AB477B}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.Data", "PoweredSoft.Data\PoweredSoft.Data.csproj", "{62DDEA81-6B09-4116-A91B-81FE66AB477B}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PoweredSoft.Data.MongoDB", "PoweredSoft.Data.MongoDB\PoweredSoft.Data.MongoDB.csproj", "{34BED188-2B88-4CAD-8DD0-6FC70D156902}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.Data.MongoDB", "PoweredSoft.Data.MongoDB\PoweredSoft.Data.MongoDB.csproj", "{34BED188-2B88-4CAD-8DD0-6FC70D156902}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.Data.EntityFramework", "PoweredSoft.Data.EntityFramework\PoweredSoft.Data.EntityFramework.csproj", "{7BB489B2-58C0-4C49-A339-70E4CE750A40}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -33,10 +33,6 @@ Global
{78EEC90C-F2C3-4B59-93DA-DE22BFD1FD30}.Debug|Any CPU.Build.0 = Debug|Any CPU {78EEC90C-F2C3-4B59-93DA-DE22BFD1FD30}.Debug|Any CPU.Build.0 = Debug|Any CPU
{78EEC90C-F2C3-4B59-93DA-DE22BFD1FD30}.Release|Any CPU.ActiveCfg = Release|Any CPU {78EEC90C-F2C3-4B59-93DA-DE22BFD1FD30}.Release|Any CPU.ActiveCfg = Release|Any CPU
{78EEC90C-F2C3-4B59-93DA-DE22BFD1FD30}.Release|Any CPU.Build.0 = Release|Any CPU {78EEC90C-F2C3-4B59-93DA-DE22BFD1FD30}.Release|Any CPU.Build.0 = Release|Any CPU
{1F0B95F6-2E97-4FC2-A452-F8A071CBEF4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F0B95F6-2E97-4FC2-A452-F8A071CBEF4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F0B95F6-2E97-4FC2-A452-F8A071CBEF4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F0B95F6-2E97-4FC2-A452-F8A071CBEF4B}.Release|Any CPU.Build.0 = Release|Any CPU
{62DDEA81-6B09-4116-A91B-81FE66AB477B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {62DDEA81-6B09-4116-A91B-81FE66AB477B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{62DDEA81-6B09-4116-A91B-81FE66AB477B}.Debug|Any CPU.Build.0 = Debug|Any CPU {62DDEA81-6B09-4116-A91B-81FE66AB477B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{62DDEA81-6B09-4116-A91B-81FE66AB477B}.Release|Any CPU.ActiveCfg = Release|Any CPU {62DDEA81-6B09-4116-A91B-81FE66AB477B}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -45,6 +41,10 @@ Global
{34BED188-2B88-4CAD-8DD0-6FC70D156902}.Debug|Any CPU.Build.0 = Debug|Any CPU {34BED188-2B88-4CAD-8DD0-6FC70D156902}.Debug|Any CPU.Build.0 = Debug|Any CPU
{34BED188-2B88-4CAD-8DD0-6FC70D156902}.Release|Any CPU.ActiveCfg = Release|Any CPU {34BED188-2B88-4CAD-8DD0-6FC70D156902}.Release|Any CPU.ActiveCfg = Release|Any CPU
{34BED188-2B88-4CAD-8DD0-6FC70D156902}.Release|Any CPU.Build.0 = Release|Any CPU {34BED188-2B88-4CAD-8DD0-6FC70D156902}.Release|Any CPU.Build.0 = Release|Any CPU
{7BB489B2-58C0-4C49-A339-70E4CE750A40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7BB489B2-58C0-4C49-A339-70E4CE750A40}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7BB489B2-58C0-4C49-A339-70E4CE750A40}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7BB489B2-58C0-4C49-A339-70E4CE750A40}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace PoweredSoft.Data.Core
{
public interface IDbContextFactory
{
IQueryable<T> GetQueryable<T>()
where T : class;
IQueryable GetQueryable(Type type);
void Add(object entity);
void Remove(object entity);
int SaveChanges();
Task<int> SaveChangesAsync();
IEnumerable<PropertyInfo> GetKeyProperties(Type entityType);
IEnumerable<Expression<Func<TEntity, object>>> GetKeyProperties<TEntity>();
}
}

View File

@ -1,11 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace PoweredSoft.Data.Core
{
public interface IDbContextFactoryProvider
{
IDbContextFactory GetContextFactory(Type contextType);
}
}

View File

@ -9,7 +9,7 @@
<RepositoryUrl>https://github.com/PoweredSoft/Data</RepositoryUrl> <RepositoryUrl>https://github.com/PoweredSoft/Data</RepositoryUrl>
<RepositoryType>github</RepositoryType> <RepositoryType>github</RepositoryType>
<PackageTags>powered,soft,orm,db,context,ef,ef6,efcore,factory</PackageTags> <PackageTags>powered,soft,orm,db,context,ef,ef6,efcore,factory</PackageTags>
<Version>1.1.3</Version> <Version>2.0.0$(VersionSuffix)</Version>
<PackageIconUrl>https://secure.gravatar.com/avatar/4e32f73820c16718909a06c2927f1f8b?s=512&amp;amp;r=g&amp;amp;d=retro</PackageIconUrl> <PackageIconUrl>https://secure.gravatar.com/avatar/4e32f73820c16718909a06c2927f1f8b?s=512&amp;amp;r=g&amp;amp;d=retro</PackageIconUrl>
<Product>PoweredSoft.Data.Core</Product> <Product>PoweredSoft.Data.Core</Product>
<Description>Library to abstract orm.</Description> <Description>Library to abstract orm.</Description>

View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using PoweredSoft.Data.Core;
namespace PoweredSoft.Data.EntityFramework
{
public class AsyncQueryableHandlerService : IAsyncQueryableHandlerService
{
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default(CancellationToken))
=> queryable.FirstOrDefaultAsync(cancellationToken);
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default(CancellationToken))
=> queryable.FirstOrDefaultAsync(predicate, cancellationToken);
public Task<List<T>> ToListAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default(CancellationToken))
=> queryable.ToListAsync(cancellationToken);
public Task<int> CountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default(CancellationToken))
=> queryable.CountAsync();
public Task<long> LongCountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default(CancellationToken))
=> queryable.LongCountAsync();
public bool CanHandle<T>(IQueryable<T> queryable) => queryable.Provider is System.Data.Entity.Infrastructure.IDbAsyncQueryProvider;
public Task<bool> AnyAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default(CancellationToken))
=> queryable.AnyAsync(predicate, cancellationToken);
public Task<bool> AnyAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default(CancellationToken))
=> queryable.AnyAsync(cancellationToken);
}
}

View File

@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.1;net461</TargetFrameworks>
<Copyright>Powered Softwares Inc.</Copyright>
<PackageLicenseUrl>MIT</PackageLicenseUrl>
<PackageProjectUrl>https://github.com/PoweredSoft/Data</PackageProjectUrl>
<RepositoryUrl>https://github.com/PoweredSoft/Data</RepositoryUrl>
<RepositoryType>github</RepositoryType>
<PackageTags>powered,soft,orm,db,context,ef,ef6,efcore,factory</PackageTags>
<Version>2.0.0$(VersionSuffix)</Version>
<PackageIconUrl>https://secure.gravatar.com/avatar/4e32f73820c16718909a06c2927f1f8b?s=512&amp;amp;r=g&amp;amp;d=retro</PackageIconUrl>
<Product>PoweredSoft.Data.EntityFramework</Product>
<Description>the abstraction implementation for EF Core.</Description>
<PackageId>PoweredSoft.Data.EntityFramework</PackageId>
<PackageReleaseNotes>N/A</PackageReleaseNotes>
<PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance>
<Company>PoweredSoft</Company>
<Authors>David Lebee</Authors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="EntityFramework" Version="6.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PoweredSoft.Data.Core\PoweredSoft.Data.Core.csproj" />
<ProjectReference Include="..\PoweredSoft.Data\PoweredSoft.Data.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,19 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using PoweredSoft.Data.Core;
using System;
using System.Collections.Generic;
using System.Text;
namespace PoweredSoft.Data.EntityFramework
{
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddPoweredSoftEntityFrameworkCoreDataServices(this IServiceCollection services)
{
services.AddPoweredSoftDataServices();
services.AddTransient<IAsyncQueryableHandlerService, AsyncQueryableHandlerService>();
return services;
}
}
}

View File

@ -1,40 +0,0 @@
using PoweredSoft.Test.Mock;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace PoweredSoft.Data.EntityFrameworkCore.Test
{
public class AsyncQueryableServiceTests
{
[Fact]
public void TestCanHandle()
{
MockContextFactory.SeedAndTestContextFor("AsyncQueryableServiceTests_TestCanHandle", TestSeeders.SimpleSeedScenario, ctx =>
{
var test = new AsyncQueryableHandlerService();
IQueryable<Order> query = ctx.Orders;
var query2 = query.GroupBy(t => t.Customer);
var query3 = query.Where(t => t.Customer.LastName == "David");
Assert.True(test.CanHandle(query));
Assert.True(test.CanHandle(query2));
Assert.True(test.CanHandle(query3));
});
}
[Fact]
public void TestFirstOrDefault()
{
MockContextFactory.SeedAndTestContextFor("AsyncQueryableServiceTests_TestCanHandle", TestSeeders.SimpleSeedScenario, async ctx =>
{
var handler = new AsyncQueryableHandlerService();
var service = new AsyncQueryableService(new[] { handler });
var first = await service.FirstOrDefaultAsync(ctx.Orders);
});
}
}
}

View File

@ -1,58 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Xunit;
using MongoDB.Driver;
using PoweredSoft.Test.Mock;
using PoweredSoft.Data.Core;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using PoweredSoft.Data.MongoDB;
namespace PoweredSoft.Data.EntityFrameworkCore.Test
{
public class CohabitTest
{
[Fact]
public void TestCohabitation()
{
var mongoHandler = new PoweredSoft.Data.MongoDB.AsyncQueryableHandlerService();
var efCoreHandler = new PoweredSoft.Data.EntityFrameworkCore.AsyncQueryableHandlerService();
var service = new PoweredSoft.Data.AsyncQueryableService(new IAsyncQueryableHandlerService[] { mongoHandler, efCoreHandler });
var mongoClient = new MongoClient();
var db = mongoClient.GetDatabase("acme");
var mongoOrders = db.GetCollection<Order>("orders").AsQueryable();
var options = new DbContextOptionsBuilder<MockContext>().UseInMemoryDatabase(databaseName: "CohabitTest_TestCohabitation").Options;
var context = new MockContext(options);
var set = context.Set<Order>();
var efCoreOrders = set.AsQueryable();
var shouldBeMongoHandler = service.GetAsyncQueryableHandler(mongoOrders);
Assert.Equal(mongoHandler, shouldBeMongoHandler);
var shouldBeEfCoreHandler = service.GetAsyncQueryableHandler(efCoreOrders);
Assert.Equal(efCoreHandler, shouldBeEfCoreHandler);
}
[Fact]
public void TestDI()
{
var services = new ServiceCollection();
services.AddPoweredSoftEntityFrameworkCoreDataServices();
services.AddPoweredSoftMongoDBDataServices();
var sp = services.BuildServiceProvider();
var result = sp.GetServices<IAsyncQueryableHandlerService>();
var someService = sp.GetService<IAsyncQueryableService>();
Assert.Equal(2, result.Count());
Assert.Equal(2, someService.Handlers.Count());
}
}
}

View File

@ -1,37 +0,0 @@
using PoweredSoft.Test.Mock;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using Xunit;
using Xunit.Abstractions;
namespace PoweredSoft.Data.EntityFrameworkCore.Test
{
public class DbContextFactoryPrimaryKeyTests
{
private readonly ITestOutputHelper output;
public DbContextFactoryPrimaryKeyTests(ITestOutputHelper output)
{
this.output = output;
}
[Fact]
public void Simple()
{
MockContextFactory.SeedAndTestContextFor("DbContextFactoryPrimaryKeyTests_Simple", TestSeeders.SimpleSeedScenario, ctx =>
{
var sw = new Stopwatch();
sw.Start();
var factory = new DbContextFactory(ctx);
var keys = factory.GetKeyProperties(typeof(Order));
Assert.Single<PropertyInfo>(keys, t => t.Name == "Id");
sw.Stop();
output.WriteLine($"Stop Watch of success took: {sw.Elapsed}");
});
}
}
}

View File

@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
namespace PoweredSoft.Test.Mock
{
public class Order
{
public long Id { get; set; }
public long OrderNum { get; set; }
public DateTime Date { get; set; }
public long CustomerId { get; set; }
public virtual Customer Customer { get; set; }
public ICollection<OrderItem> OrderItems { get; set; } = new HashSet<OrderItem>();
}
public class Customer
{
public long Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<Order> Orders { get; set; } = new HashSet<Order>();
}
public class Item
{
public long Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public virtual ICollection<OrderItem> OrderItems { get; set; } = new HashSet<OrderItem>();
}
public class OrderItem
{
public long Id { get; set; }
public long Quantity { get; set; }
public decimal PriceAtTheTime { get; set; }
public long ItemId { get; set; }
public long OrderId { get; set; }
public virtual Item Item { get; set; }
public virtual Order Order { get; set; }
}
}

View File

@ -1,32 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.EntityFrameworkCore;
namespace PoweredSoft.Test.Mock
{
public class MockContext : DbContext
{
public virtual DbSet<Customer> Customers { get; set; }
public virtual DbSet<Item> Items { get; set; }
public virtual DbSet<Order> Orders { get; set; }
public virtual DbSet<OrderItem> OrderItems { get; set; }
public virtual DbSet<Ticket> Tickets { get; set; }
public MockContext()
{
}
public MockContext(DbContextOptions<MockContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
}
}

View File

@ -1,25 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.EntityFrameworkCore;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol;
using Xunit.Sdk;
namespace PoweredSoft.Test.Mock
{
public static class MockContextFactory
{
public static void TestContextFor(string testName, Action<MockContext> action)
{
var options = new DbContextOptionsBuilder<MockContext>().UseInMemoryDatabase(databaseName: testName).Options;
using (var ctx = new MockContext(options))
action(ctx);
}
public static void SeedAndTestContextFor(string testName, Action<string> seedAction, Action<MockContext> action)
{
seedAction(testName);
TestContextFor(testName, action);
}
}
}

View File

@ -1,139 +0,0 @@
using System;
using System.Collections.Generic;
namespace PoweredSoft.Test.Mock
{
public static class TestSeeders
{
public static void SimpleSeedScenario(string testName)
{
MockContextFactory.TestContextFor(testName, ctx =>
{
ctx.AddRange(new Customer[]
{
new Customer() { Id = 1, FirstName = "David", LastName = "Lebee" },
new Customer() { Id = 2, FirstName = "John", LastName = "Doe" },
new Customer() { Id = 3, FirstName = "Chuck", LastName = "Norris" },
new Customer() { Id = 4, FirstName = "Nelson", LastName = "Mendela" },
new Customer() { Id = 5, FirstName = "Jimi", LastName = "Hendrix" },
new Customer() { Id = 6, FirstName = "Axel", LastName = "Rose" },
new Customer() { Id = 7, FirstName = "John", LastName = "Frusciante" },
new Customer() { Id = 8, FirstName = "Michael", LastName = "Jackson" },
new Customer() { Id = 9, FirstName = "Anita", LastName = "Franklin" },
});
ctx.AddRange(new Item[]
{
new Item { Id = 1, Name = "Computer", Price = 1000M },
new Item { Id = 2, Name = "Mice", Price = 25.99M },
new Item { Id = 3, Name = "Keyboard", Price = 100M },
new Item { Id = 4, Name = "Screen", Price = 499.98M },
new Item { Id = 5, Name = "Printer", Price = 230.95M },
new Item { Id = 6, Name = "HDMI Cables", Price = 20M },
new Item { Id = 7, Name = "Power Cables", Price = 5.99M }
});
ctx.Orders.AddRange(new Order[]
{
new Order()
{
Id = 1,
OrderNum = 1000,
CustomerId = 1,
Date = new DateTime(2018, 1, 1),
OrderItems = new List<OrderItem>()
{
new OrderItem() { Id = 1, ItemId = 1, PriceAtTheTime = 1000M, Quantity = 1 },
new OrderItem() { Id = 2, ItemId = 2, PriceAtTheTime = 30M, Quantity = 1 },
new OrderItem() { Id = 3, ItemId = 4, PriceAtTheTime = 399.99M, Quantity = 2 },
new OrderItem() { Id = 4, ItemId = 6, PriceAtTheTime = 20, Quantity = 2 },
new OrderItem() { Id = 8, ItemId = 6, PriceAtTheTime = 3.99M, Quantity = 3 }
}
},
new Order()
{
Id = 2,
OrderNum = 1001,
CustomerId = 2,
Date = new DateTime(2018, 2, 1),
OrderItems = new List<OrderItem>()
{
new OrderItem() { Id = 9, ItemId = 6, PriceAtTheTime = 20, Quantity = 2 },
new OrderItem() { Id = 10, ItemId = 6, PriceAtTheTime = 3.99M, Quantity = 3 }
}
},
new Order()
{
Id = 3,
OrderNum = 1002,
CustomerId = 3,
Date = new DateTime(2018, 2, 1),
OrderItems = new List<OrderItem>()
{
new OrderItem() { Id = 11, ItemId = 5, PriceAtTheTime = 499.99M, Quantity = 1 },
new OrderItem() { Id = 12, ItemId = 6, PriceAtTheTime = 20, Quantity = 1 },
new OrderItem() { Id = 13, ItemId = 7, PriceAtTheTime = 3.99M, Quantity = 1 }
}
},
new Order()
{
Id = 4,
OrderNum = 1003,
CustomerId = 1,
Date = new DateTime(2018, 3, 1),
OrderItems = new List<OrderItem>()
{
new OrderItem() { Id = 14, ItemId = 2, PriceAtTheTime = 50M, Quantity = 1 },
new OrderItem() { Id = 15, ItemId = 3, PriceAtTheTime = 75.50M, Quantity = 1 },
}
}
});
ctx.SaveChanges();
});
}
internal static void SeedTicketScenario(string testName)
{
MockContextFactory.TestContextFor(testName, ctx =>
{
var faker = new Bogus.Faker<Ticket>()
.RuleFor(t => t.TicketType, (f, u) => f.PickRandom("new", "open", "refused", "closed"))
.RuleFor(t => t.Title, (f, u) => f.Lorem.Sentence())
.RuleFor(t => t.Details, (f, u) => f.Lorem.Paragraph())
.RuleFor(t => t.IsHtml, (f, u) => false)
.RuleFor(t => t.TagList, (f, u) => string.Join(",", f.Commerce.Categories(3)))
.RuleFor(t => t.CreatedDate, (f, u) => f.Date.Recent(100))
.RuleFor(t => t.Owner, (f, u) => f.Person.FullName)
.RuleFor(t => t.AssignedTo, (f, u) => f.Person.FullName)
.RuleFor(t => t.TicketStatus, (f, u) => f.PickRandom(1, 2, 3))
.RuleFor(t => t.LastUpdateBy, (f, u) => f.Person.FullName)
.RuleFor(t => t.LastUpdateDate, (f, u) => f.Date.Soon(5))
.RuleFor(t => t.Priority, (f, u) => f.PickRandom("low", "medium", "high", "critical"))
.RuleFor(t => t.AffectedCustomer, (f, u) => f.PickRandom(true, false))
.RuleFor(t => t.Version, (f, u) => f.PickRandom("1.0.0", "1.1.0", "2.0.0"))
.RuleFor(t => t.ProjectId, (f, u) => f.Random.Number(100))
.RuleFor(t => t.DueDate, (f, u) => f.Date.Soon(5))
.RuleFor(t => t.EstimatedDuration, (f, u) => f.Random.Number(20))
.RuleFor(t => t.ActualDuration, (f, u) => f.Random.Number(20))
.RuleFor(t => t.TargetDate, (f, u) => f.Date.Soon(5))
.RuleFor(t => t.ResolutionDate, (f, u) => f.Date.Soon(5))
.RuleFor(t => t.Type, (f, u) => f.PickRandom(1, 2, 3))
.RuleFor(t => t.ParentId, () => 0)
.RuleFor(t => t.PreferredLanguage, (f, u) => f.PickRandom("fr", "en", "es"))
;
var fakeModels = new List<Ticket>();
for (var i = 0; i < 500; i++)
{
var t = faker.Generate();
t.TicketId = i + 1;
fakeModels.Add(t);
}
ctx.AddRange(fakeModels);
ctx.SaveChanges();
});
}
}
}

View File

@ -1,36 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace PoweredSoft.Test.Mock
{
public class Ticket
{
public int TicketId { get; set; }
public string TicketType { get; set; }
public string Title { get; set; }
public string Details { get; set; }
public bool IsHtml { get; set; }
public string TagList { get; set; }
public DateTimeOffset CreatedDate { get; set; }
public string Owner { get; set; }
public string AssignedTo { get; set; }
public int TicketStatus { get; set; }
public DateTimeOffset CurrentStatusDate { get; set; }
public string CurrentStatusSetBy { get; set; }
public string LastUpdateBy { get; set; }
public DateTimeOffset LastUpdateDate { get; set; }
public string Priority { get; set; }
public bool AffectedCustomer { get; set; }
public string Version { get; set; }
public int ProjectId { get; set; }
public DateTimeOffset DueDate { get; set; }
public decimal EstimatedDuration { get; set; }
public decimal ActualDuration { get; set; }
public DateTimeOffset TargetDate { get; set; }
public DateTimeOffset ResolutionDate { get; set; }
public int Type { get; set; }
public int ParentId { get; set; }
public string PreferredLanguage { get; set; }
}
}

View File

@ -1,23 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Bogus" Version="24.3.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.1.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="MongoDB.Driver" Version="2.7.3" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PoweredSoft.Data.EntityFrameworkCore\PoweredSoft.Data.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\PoweredSoft.Data.MongoDB\PoweredSoft.Data.MongoDB.csproj" />
</ItemGroup>
</Project>

View File

@ -1,67 +0,0 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal;
using PoweredSoft.Data.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
namespace PoweredSoft.Data.EntityFrameworkCore
{
public class DbContextFactory : IDbContextFactory
{
private readonly DbContext _context;
public DbContextFactory(DbContext dbContext)
{
_context = dbContext;
}
public void Add(object entity) => _context.Add(entity);
public IQueryable<T> GetQueryable<T>() where T : class => _context.Set<T>();
public IQueryable GetQueryable(Type type)
{
var setSource = (IDbSetSource)this._context.GetType().GetProperty("SetSource", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(_context);
var ret = (IQueryable)((IDbSetCache)this).GetOrAddSet(setSource, type);
return ret;
}
public void Remove(object entity)
{
_context.Remove(entity);
}
public int SaveChanges() => _context.SaveChanges();
public async Task<int> SaveChangesAsync() => await _context.SaveChangesAsync();
public IEnumerable<PropertyInfo> GetKeyProperties(Type entityType)
{
var key = _context.Model.FindEntityType(entityType).FindPrimaryKey();
var keysProperties = key.Properties.Select(t => t.PropertyInfo);
return keysProperties;
}
public IEnumerable<Expression<Func<TEntity, object>>> GetKeyProperties<TEntity>()
{
var keyProps = GetKeyProperties(typeof(TEntity));
var parameter = Expression.Parameter(typeof(TEntity));
var result = keyProps
.Select(keyProp =>
{
var property = Expression.Property(parameter, keyProp);
var funcType = typeof(Expression<Func<TEntity, object>>);
var lambda = Expression.Lambda(funcType, Expression.Convert(property, typeof(Object)), parameter);
return (Expression<Func<TEntity, object>>)lambda;
})
.ToList();
return result;
}
}
}

View File

@ -1,26 +0,0 @@
using PoweredSoft.Data.Core;
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
namespace PoweredSoft.Data.EntityFrameworkCore
{
public class DbContextFactoryProvider : IDbContextFactoryProvider
{
private readonly IServiceProvider serviceProvider;
public DbContextFactoryProvider(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public IDbContextFactory GetContextFactory(Type contextType)
{
var dbContext = this.serviceProvider.GetRequiredService(contextType) as DbContext;
var dbContextFactory = new DbContextFactory(dbContext);
return dbContextFactory;
}
}
}

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netstandard2.1</TargetFramework>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Copyright>Powered Softwares Inc.</Copyright> <Copyright>Powered Softwares Inc.</Copyright>
<PackageLicenseUrl>MIT</PackageLicenseUrl> <PackageLicenseUrl>MIT</PackageLicenseUrl>
@ -9,7 +9,7 @@
<RepositoryUrl>https://github.com/PoweredSoft/Data</RepositoryUrl> <RepositoryUrl>https://github.com/PoweredSoft/Data</RepositoryUrl>
<RepositoryType>github</RepositoryType> <RepositoryType>github</RepositoryType>
<PackageTags>powered,soft,orm,db,context,ef,ef6,efcore,factory</PackageTags> <PackageTags>powered,soft,orm,db,context,ef,ef6,efcore,factory</PackageTags>
<Version>1.1.3</Version> <Version>2.0.0$(VersionSuffix)</Version>
<PackageIconUrl>https://secure.gravatar.com/avatar/4e32f73820c16718909a06c2927f1f8b?s=512&amp;amp;r=g&amp;amp;d=retro</PackageIconUrl> <PackageIconUrl>https://secure.gravatar.com/avatar/4e32f73820c16718909a06c2927f1f8b?s=512&amp;amp;r=g&amp;amp;d=retro</PackageIconUrl>
<Product>PoweredSoft.Data.EntityFrameworkCore</Product> <Product>PoweredSoft.Data.EntityFrameworkCore</Product>
<Description>the abstraction implementation for EF Core.</Description> <Description>the abstraction implementation for EF Core.</Description>
@ -21,7 +21,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.4" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -12,7 +12,6 @@ namespace PoweredSoft.Data.EntityFrameworkCore
public static IServiceCollection AddPoweredSoftEntityFrameworkCoreDataServices(this IServiceCollection services) public static IServiceCollection AddPoweredSoftEntityFrameworkCoreDataServices(this IServiceCollection services)
{ {
services.AddPoweredSoftDataServices(); services.AddPoweredSoftDataServices();
services.TryAddTransient<IDbContextFactoryProvider, DbContextFactoryProvider>();
services.AddTransient<IAsyncQueryableHandlerService, AsyncQueryableHandlerService>(); services.AddTransient<IAsyncQueryableHandlerService, AsyncQueryableHandlerService>();
return services; return services;
} }

View File

@ -9,7 +9,7 @@
<RepositoryUrl>https://github.com/PoweredSoft/Data</RepositoryUrl> <RepositoryUrl>https://github.com/PoweredSoft/Data</RepositoryUrl>
<RepositoryType>github</RepositoryType> <RepositoryType>github</RepositoryType>
<PackageTags>powered,soft,async,queryable,handler</PackageTags> <PackageTags>powered,soft,async,queryable,handler</PackageTags>
<Version>1.1.3</Version> <Version>2.0.0$(VersionSuffix)</Version>
<PackageIconUrl>https://secure.gravatar.com/avatar/4e32f73820c16718909a06c2927f1f8b?s=512&amp;amp;r=g&amp;amp;d=retro</PackageIconUrl> <PackageIconUrl>https://secure.gravatar.com/avatar/4e32f73820c16718909a06c2927f1f8b?s=512&amp;amp;r=g&amp;amp;d=retro</PackageIconUrl>
<Product>PoweredSoft.Data.MongoDB</Product> <Product>PoweredSoft.Data.MongoDB</Product>
<Description>the abstraction implementation for MongoDB.</Description> <Description>the abstraction implementation for MongoDB.</Description>
@ -21,8 +21,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.0" />
<PackageReference Include="MongoDB.Driver" Version="2.7.3" /> <PackageReference Include="MongoDB.Driver" Version="2.9.3" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -9,7 +9,7 @@
<RepositoryUrl>https://github.com/PoweredSoft/Data</RepositoryUrl> <RepositoryUrl>https://github.com/PoweredSoft/Data</RepositoryUrl>
<RepositoryType>github</RepositoryType> <RepositoryType>github</RepositoryType>
<PackageTags>async,queryable,handler,service,di</PackageTags> <PackageTags>async,queryable,handler,service,di</PackageTags>
<Version>1.1.3</Version> <Version>2.0.0$(VersionSuffix)</Version>
<PackageIconUrl>https://secure.gravatar.com/avatar/4e32f73820c16718909a06c2927f1f8b?s=512&amp;amp;r=g&amp;amp;d=retro</PackageIconUrl> <PackageIconUrl>https://secure.gravatar.com/avatar/4e32f73820c16718909a06c2927f1f8b?s=512&amp;amp;r=g&amp;amp;d=retro</PackageIconUrl>
<Product>PoweredSoft.Data</Product> <Product>PoweredSoft.Data</Product>
<Description>Library to abstract orm.</Description> <Description>Library to abstract orm.</Description>
@ -25,7 +25,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,5 +1,4 @@
# IDbContextFactory # Goal
The goal of this project is to help, fill the gap of supporting multiple ORM's in DynamicQuery, and possibly more projects in the future. The goal of this project is to help, fill the gap of supporting multiple ORM's in DynamicQuery, and possibly more projects in the future.
One of the most obvious reason is to be able to execute async/await operations on the context without, the executing library to be dependant on the ORM Framework such as (EF Core, EF6). One of the most obvious reason is to be able to execute async/await operations on the context without, the executing library to be dependant on the ORM Framework such as (EF Core, EF6).
@ -32,23 +31,9 @@ public class Startup
} }
``` ```
> Then somewhere else. ## AsyncQueryableService
```csharp Also as the same kind of goal, will slowly add support for a non dependant to orm/drivers async method.
public class SomeClass
{
private readonly IDbContextFactory contextFactory;
public SomeClass(IDbContextFactoryProvider dbContextFactoryProvider)
{
contextFactory = dbContextFactoryProvider.GetContextFactory(typeof(YourFavoriteContext));
}
}
```
## AsyncQueryableFactory
Also as the same kind of goal, will slowly add support for a non dependant to orm async method.
```csharp ```csharp
public interface IAsyncQueryableHandlerService public interface IAsyncQueryableHandlerService
@ -70,7 +55,7 @@ How to use
public class SomeClass public class SomeClass
{ {
private readonly IAsyncQueryableService asyncQueryableService; private readonly IAsyncQueryableService asyncQueryableService;
public SomeClass(IDbContextFactoryProvider asyncQueryableService) public SomeClass(IAsyncQueryableService asyncQueryableService)
{ {
this.asyncQueryableService = asyncQueryableService; this.asyncQueryableService = asyncQueryableService;
} }