Skip to content

Commit e57c4b8

Browse files
authored
Merge pull request #19 from vany0114/vany0114-net-standard-21
Support for .Net Standard 2.1
2 parents de80b2c + 3fdd930 commit e57c4b8

File tree

7 files changed

+111
-83
lines changed

7 files changed

+111
-83
lines changed

.gitignore

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ UpgradeLog*.htm
220220
*.mdf
221221
*.ldf
222222
*.ndf
223-
223+
224224
# Business Intelligence projects
225225
*.rdl.data
226226
*.bim.layout
@@ -286,3 +286,11 @@ __pycache__/
286286
*.btm.cs
287287
*.odx.cs
288288
*.xsd.cs
289+
290+
artifacts
291+
build
292+
tools
293+
294+
*.lock.json
295+
*.nuget.targets
296+
*.nuget.props

README.md

Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
[![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=With+EF.DbContextFactory+you+can+resolve+easily+your+DbContext+dependencies+in+a+safe+way+injecting+a+factory+instead+of+an+instance+itself%2C+enabling+you+to+work+in+multi-thread+contexts+with+Entity+Framework+or+just+work+safest+with+DbContext+following+the+Microsoft+recommendations+about+the+DbContext+lifetime.&url=https://github.com/vany0114/EF.DbContextFactory&hashtags=EF.DbContextFactory,EntityFramework,DbContext,Thread-Safe)
1212

1313

14-
With EF.DbContextFactory you can resolve easily your DbContext dependencies in a safe way injecting a factory instead of an instance itself, enabling you to work in [multi-thread contexts](https://msdn.microsoft.com/en-us/library/jj729737(v=vs.113).aspx?f=255&mspperror=-2147217396#Anchor_3) with Entity Framework or just work safest with DbContext following the Microsoft recommendations about the [DbContext lifecycle](https://msdn.microsoft.com/en-us/library/jj729737(v=vs.113).aspx?f=255&mspperror=-2147217396#Anchor_1) but keeping your code clean and testable using dependency injection pattern.
14+
With EF.DbContextFactory you can resolve easily your DbContext dependencies in a safe way injecting a factory instead of an instance itself, enabling you to work in [multi-thread contexts](https://msdn.microsoft.com/en-us/library/jj729737(v=vs.113).aspx?f=255&mspperror=-2147217396#Anchor_3) with Entity Framework Core or just work safest with DbContext following the Microsoft recommendations about the [DbContext lifecycle](https://msdn.microsoft.com/en-us/library/jj729737(v=vs.113).aspx?f=255&mspperror=-2147217396#Anchor_1) but keeping your code clean and testable using dependency injection pattern.
1515

1616
## Package Status ##
1717

1818
|<span> | | |
1919
|---|---|---|
20-
|[EFCore.DbContextFactory](#aspnet-core) |[![](https://img.shields.io/nuget/v/EFCore.DbContextFactory.svg)](https://www.nuget.org/packages/EFCore.DbContextFactory/) |[![NuGet](https://img.shields.io/nuget/dt/EFCore.DbContextFactory.svg)](https://www.nuget.org/packages/EFCore.DbContextFactory/) |
20+
|[EFCore.DbContextFactory](#efcoredbcontextfactory) |[![](https://img.shields.io/nuget/v/EFCore.DbContextFactory.svg)](https://www.nuget.org/packages/EFCore.DbContextFactory/) |[![NuGet](https://img.shields.io/nuget/dt/EFCore.DbContextFactory.svg)](https://www.nuget.org/packages/EFCore.DbContextFactory/) |
2121
|[EF.DbContextFactory.Unity](#unity-aspnet-mvc-and-web-api) |[![](https://img.shields.io/nuget/v/EF.DbContextFactory.Unity.svg)](https://www.nuget.org/packages/EF.DbContextFactory.Unity/) |[![NuGet](https://img.shields.io/nuget/dt/EF.DbContextFactory.Unity.svg)](https://www.nuget.org/packages/EF.DbContextFactory.Unity/) |
2222
|[EF.DbContextFactory.Ninject](#ninject-aspnet-mvc-and-web-api) |[![](https://img.shields.io/nuget/v/EF.DbContextFactory.Ninject.svg)](https://www.nuget.org/packages/EF.DbContextFactory.Ninject/) |[![NuGet](https://img.shields.io/nuget/dt/EF.DbContextFactory.Ninject.svg)](https://www.nuget.org/packages/EF.DbContextFactory.Ninject/) |
2323
|[EF.DbContextFactory.StructureMap](#structuremap-aspnet-mvc-and-web-api) |[![](https://img.shields.io/nuget/v/EF.DbContextFactory.StructureMap.svg)](https://www.nuget.org/packages/EF.DbContextFactory.StructureMap/) |[![NuGet](https://img.shields.io/nuget/dt/EF.DbContextFactory.StructureMap.svg)](https://www.nuget.org/packages/EF.DbContextFactory.StructureMap/) |
@@ -41,19 +41,17 @@ There are multiple solutions to manage concurrency scenarios from data perspecti
4141

4242
## Motivation :sunglasses:
4343

44-
I have worked with Entity Framework in a lot of projects, it’s very useful, it can make you more productive and it has a lot of great features that make it an awesome ORM, but like everything in the world, it has its downsides or issues. Sometime I was working in a project with concurrency scenarios, reading a queue from a message bus, sending messages to another bus with SignalR and so on. Everything was going good until I did a real test with multiple users connected at the same time, it turns out Entity Framework doesn’t work fine in that scenario. I did know that DbContext is not thread safe therefore I was injecting my DbContext instance per request following the Microsoft recommendatios so every request would has a new instance and then avoid problems sharing the contexts and state’s entities inside the context, but it doesn’t work in concurrency scenarios. I really had a problem, beause I didn’t want to hardcode DbContext creation inside my repository using the using statement to create and dispose inmediatly, but I had to support concurrency scenarios with Entity Framework in a proper way. So I remembered sometime studying the awesome CQRS Journey Microsoft project, where those guys were injecting their repositories like a factory and one of them explained me why. This was his answer:
44+
I have worked with Entity Framework in a lot of projects, it’s very useful, it can make you more productive and it has a lot of great features that make it an awesome ORM, but like everything in the world, it has its downsides or issues. Sometime I was working on a project with concurrency scenarios, reading a queue from a message bus, sending messages to another bus with SignalR and so on. Everything was going good until I did a real test with multiple users connected at the same time, it turns out Entity Framework doesn’t work fine in that scenario. I did know that DbContext is not thread safe therefore I was injecting my DbContext instance per request following the Microsoft recommendatios so every request would has a new instance and then avoid problems sharing the contexts and state’s entities inside the context, but it doesn’t work in concurrency scenarios. I really had a problem, beause I didn’t want to hardcode DbContext creation inside my repository using the `using` statement to create and dispose inmediatly, but I had to support concurrency scenarios with Entity Framework in a proper way. So I remembered sometime studying the awesome CQRS Journey Microsoft project, where those guys were injecting their repositories like a factory and one of them explained me why. This was his answer:
4545

4646
> ***"This is to avoid having a permanent reference to an instance of the context. Entity Framework context life cycles should be as short as possible. Using a delegate, the context is instantiated and disposed inside the class it is injected in and on every needs."***
4747
4848
## Getting Started :grinning:
4949

50-
EF.DbContextFactory provides you integration with most popular dependency injection frameworks such as [Unity](https://github.com/unitycontainer/unity), [Ninject](http://www.ninject.org/), [Structuremap](http://structuremap.github.io/), [Simple Injector](https://simpleinjector.org/index.html) and [.Net Core](https://dotnet.github.io/). So there five Nuget packages so far listed above that you can use like an extension to inject your DbContext as a factory.
50+
EF.DbContextFactory provides you extensions to inject the `DbContext` as a factory using the Microsoft default implementation of dependency injection for `Microsoft.Extensions.DependencyInjection` as well as integration with most popular dependency injection frameworks such as [Unity](https://github.com/unitycontainer/unity), [Ninject](http://www.ninject.org/), [Structuremap](http://structuremap.github.io/), [Simple Injector](https://simpleinjector.org/index.html). So there are five Nuget packages so far listed above that you can use like an extension to inject your DbContext as a factory.
5151

5252
All of nuget packages add a generic extension method to the dependency injection framework container called `AddDbContextFactory`. It needs the derived DbContext Type and as an optional parameter, the name or the connection string itself. ***If you have the default one (DefaultConnection) in the configuration file, you dont need to specify it***
5353

54-
> **EFCore.DbContextFactory** nuget package is slightly different and will be explained later.
55-
56-
The other thing what you need is to inject your DbContext as a factory instead of the instance itself:
54+
You just need to inject your DbContext as a factory instead of the instance itself:
5755

5856
```cs
5957
public class OrderRepositoryWithFactory : IOrderRepository
@@ -99,6 +97,53 @@ public class OrderRepositoryWithFactory : IOrderRepository
9997
}
10098
}
10199
```
100+
### EFCore.DbContextFactory
101+
If you are using the Microsoft DI container you only need to install [EFCore.DbContextFactory](https://www.nuget.org/packages/EFCore.DbContextFactory/) nuget package. After that, you are able to access to the extension method from the `ServiceCollection` object.
102+
103+
>EFCore.DbContextFactory supports `netstandard2.0` and `netstandard2.1`
104+
105+
The easiest way to resolve your DbContext factory is using the extension method called `AddSqlServerDbContextFactory`. It automatically configures your DbContext to use SqlServer and you can pass it optionally the name or the connection string itself ***If you have the default one (DefaultConnection) in the configuration file, you dont need to specify it*** and your `ILoggerFactory`, if you want.
106+
107+
```cs
108+
using EFCore.DbContextFactory.Extensions;
109+
.
110+
.
111+
.
112+
services.AddSqlServerDbContextFactory<OrderContext>();
113+
```
114+
115+
Also you can use the known method `AddDbContextFactory` with the difference that it receives the `DbContextOptionsBuilder` object so you’re able to build your DbContext as you need.
116+
117+
```cs
118+
var dbLogger = new LoggerFactory(new[]
119+
{
120+
new ConsoleLoggerProvider((category, level)
121+
=> category == DbLoggerCategory.Database.Command.Name
122+
&& level == LogLevel.Information, true)
123+
});
124+
125+
// ************************************sql server**********************************************
126+
// this is like if you had called the AddSqlServerDbContextFactory method.
127+
services.AddDbContextFactory<OrderContext>(builder => builder
128+
.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
129+
.UseLoggerFactory(dbLogger));
130+
131+
services.AddDbContextFactory<OrderContext>((provider, builder) => builder
132+
.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
133+
134+
// ************************************sqlite**************************************************
135+
services.AddDbContextFactory<OrderContext>(builder => builder
136+
.UseSqlite(Configuration.GetConnectionString("DefaultConnection"))
137+
.UseLoggerFactory(dbLogger));
138+
139+
// ************************************in memory***********************************************
140+
services.AddDbContextFactory<OrderContext>(builder => builder
141+
.UseInMemoryDatabase("OrdersExample")
142+
.UseLoggerFactory(dbLogger));
143+
```
144+
145+
> You can find more examples [here](https://github.com/vany0114/EF.DbContextFactory.Samples)
146+
102147

103148
### Ninject Asp.Net Mvc and Web Api
104149
If you are using Ninject as DI container into your Asp.Net Mvc or Web Api project you must install [EF.DbContextFactory.Ninject](https://www.nuget.org/packages/EF.DbContextFactory.Ninject/) nuget package. After that, you are able to access to the extension method from the `Kernel` object from Ninject.
@@ -155,54 +200,9 @@ using EF.DbContextFactory.SimpleInjector.Extensions;
155200
container.AddDbContextFactory<OrderContext>();
156201
```
157202

158-
### Asp.Net Core
159-
If you are working with Asp.Net Core you probably know that it brings its own Dependency Injection container, so you don't need to install another package or framework to deal with it. So you only need to install [EFCore.DbContextFactory](https://www.nuget.org/packages/EFCore.DbContextFactory/) nuget package. After that, you are able to access to the extension method from the `ServiceCollection` object from Asp.Net Core.
160-
161-
>EFCore.DbContextFactory is supported from .Net Core 2.0.
162-
163-
The easiest way to resolve your DbContext factory is using the extension method called `AddSqlServerDbContextFactory`. It automatically configures your DbContext to use SqlServer and you can pass it optionally the name or the connection string itself ***If you have the default one (DefaultConnection) in the configuration file, you dont need to specify it*** and your `ILoggerFactory`, if you want.
164-
165-
```cs
166-
using EFCore.DbContextFactory.Extensions;
167-
.
168-
.
169-
.
170-
services.AddSqlServerDbContextFactory<OrderContext>();
171-
```
172-
173-
Also you can use the known method `AddDbContextFactory` with the difference that it receives the `DbContextOptionsBuilder` object so you’re able to build your DbContext as you need.
174-
175-
```cs
176-
var dbLogger = new LoggerFactory(new[]
177-
{
178-
new ConsoleLoggerProvider((category, level)
179-
=> category == DbLoggerCategory.Database.Command.Name
180-
&& level == LogLevel.Information, true)
181-
});
182-
183-
// ************************************sql server**********************************************
184-
// this is like if you had called the AddSqlServerDbContextFactory method.
185-
services.AddDbContextFactory<OrderContext>(builder => builder
186-
.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
187-
.UseLoggerFactory(dbLogger));
188-
189-
services.AddDbContextFactory<OrderContext>((provider, builder) => builder
190-
.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
191-
192-
// ************************************sqlite**************************************************
193-
services.AddDbContextFactory<OrderContext>(builder => builder
194-
.UseSqlite(Configuration.GetConnectionString("DefaultConnection"))
195-
.UseLoggerFactory(dbLogger));
196-
197-
// ************************************in memory***********************************************
198-
services.AddDbContextFactory<OrderContext>(builder => builder
199-
.UseInMemoryDatabase("OrdersExample")
200-
.UseLoggerFactory(dbLogger));
201-
```
202-
203203
## Examples :metal:
204204

205-
You can take a look at the [examples](https://github.com/vany0114/EF.DbContextFactory/tree/master/src/Examples) to see every extension in action with `Ninject`, `Structuremap`, `Structuremap.WebApi`, `Unity`, `SimpleInjector` and `Asp.Net Core`, all you need is to run the migrations and that's it. Every example project has two controllers, one to receive a repository that implements the `DbContextFactory` and another one that doesn't, and every one creates and deletes orders at the same time in different threads to simulate the concurrency. So you can see how the one that doesn't implement the `DbContextFactory` throws errors related to concurrency issues.
205+
You can take a look at the [examples](https://github.com/vany0114/EF.DbContextFactory/tree/master/src/Examples) to see every extension in action, all you need is to run the migrations and that's it. Every example project has two controllers, one to receive a repository that implements the `DbContextFactory` and another one that doesn't, and every one creates and deletes orders at the same time in different threads to simulate the concurrency. So you can see how the one that doesn't implement the `DbContextFactory` throws errors related to concurrency issues.
206206

207207
![](example.gif)
208208

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
## 2.0.0
2+
- Support for .NetStandard 2.0 and 2.1
3+
- For .NetStandard 2.0 supports EntityFrameworkCore from 2.0.0
4+
- For .NetStandard 2.1 supports EntityFrameworkCore from 3.0.0
5+
- The package is now signed
6+
### Breaking changes:
7+
- Got rid of Microsoft.AspNetCore.All reference
Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
5-
<Authors>Geovanny Alzate Sandoval</Authors>
4+
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
5+
<Version>2.0.0</Version>
6+
<AssemblyVersion>2.0.0</AssemblyVersion>
7+
<FileVersion>2.0.0</FileVersion>
8+
<InformationalVersion>2.0.0</InformationalVersion>
9+
<PackageVersion>2.0.0</PackageVersion>
610
<Company>Geovanny Alzate Sandoval</Company>
7-
<Version>1.0.2</Version>
8-
<AssemblyVersion>1.0.0.2</AssemblyVersion>
9-
<FileVersion>1.0.0.2</FileVersion>
11+
<Copyright>Copyright (c) 2017, Geovanny Alzate Sandoval</Copyright>
12+
<Description>With EFCore.DbContextFactory you can resolve easily your DbContext dependencies in a safe way injecting a factory instead of an instance itself, enabling you to work in multi-thread contexts with Entity Framework Core or just work safest with DbContext following the Microsoft recommendations about the DbContext lifetime.</Description>
13+
<DefaultLanguage>en-US</DefaultLanguage>
14+
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
15+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
16+
<Authors>Geovanny Alzate Sandoval</Authors>
17+
<AssemblyOriginatorKeyFile>EFCore.DbContextFactory.snk</AssemblyOriginatorKeyFile>
18+
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
19+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
20+
<SignAssembly>true</SignAssembly>
1021
</PropertyGroup>
1122

1223
<ItemGroup>
@@ -19,4 +30,13 @@
1930
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0" />
2031
</ItemGroup>
2132

33+
<PropertyGroup Label="NuspecProperties">
34+
<NeutralLanguage>en-US</NeutralLanguage>
35+
<AssemblyTitle>EFCore.DbContextFactory</AssemblyTitle>
36+
<PackageLicenseExpression>MIT</PackageLicenseExpression>
37+
<PackageIconUrl>https://raw.githubusercontent.com/vany0114/EF.DbContextFactory/master/nuget-icon.png</PackageIconUrl>
38+
<PackageProjectUrl>https://github.com/vany0114/EF.DbContextFactory</PackageProjectUrl>
39+
<PackageTags>EF EntityFramework EntityFrameworkCore dotnet dotnetcore DI IoC DbContext DbContextFactory ThreadSafe MultiThread Thread-Safe Multi-Thread DependencyInjection Dependency-Injection InverionOfControl Inversion-Of-Control Entity-Framework dotnet-core dot-net-core</PackageTags>
40+
<PackageReleaseNotes>See https://github.com/vany0114/EF.DbContextFactory/blob/master/src/Extensions/EFCore.DbContextFactory/CHANGELOG.md for details</PackageReleaseNotes>
41+
</PropertyGroup>
2242
</Project>
Binary file not shown.

src/Extensions/EFCore.DbContextFactory/Extensions/ServiceCollectionExtensions.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99

1010
namespace EFCore.DbContextFactory.Extensions
1111
{
12+
/// <summary>
13+
/// Extensions to add AddDbContextFactory
14+
/// </summary>
1215
public static class ServiceCollectionExtensions
1316
{
1417
/// <summary>
@@ -17,7 +20,7 @@ public static class ServiceCollectionExtensions
1720
/// <typeparam name="TDataContext">The DbContext.</typeparam>
1821
/// <param name="services"></param>
1922
/// <param name="nameOrConnectionString">Name or connection string of the context. (Optional)</param>
20-
/// <param name="logger">The <see cref="ILoggerFactory" implementation./></param>
23+
/// <param name="logger">The <see cref="ILoggerFactory"/>implementation.</param>
2124
public static void AddSqlServerDbContextFactory<TDataContext>(this IServiceCollection services, string nameOrConnectionString = null, ILoggerFactory logger = null)
2225
where TDataContext : DbContext
2326
{

0 commit comments

Comments
 (0)