Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
netcoreplus
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
tsai
netcoreplus
Commits
707e93cb
Commit
707e93cb
authored
May 18, 2019
by
阿星Plus
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
EF Done.
parent
3fd5c627
Changes
35
Show whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
1549 additions
and
2 deletions
+1549
-2
IPlusDbContextConfigurer.cs
...EntityFramework/Configuration/IPlusDbContextConfigurer.cs
+14
-0
IPlusEfCoreConfiguration.cs
...EntityFramework/Configuration/IPlusEfCoreConfiguration.cs
+13
-0
PlusDbContextConfiguration.cs
...tityFramework/Configuration/PlusDbContextConfiguration.cs
+27
-0
PlusDbContextConfigurerAction.cs
...yFramework/Configuration/PlusDbContextConfigurerAction.cs
+25
-0
PlusEfCoreConfiguration.cs
....EntityFramework/Configuration/PlusEfCoreConfiguration.cs
+29
-0
DefaultDbContextResolver.cs
src/Plus.EntityFramework/DefaultDbContextResolver.cs
+103
-0
EfCoreActiveTransactionProvider.cs
src/Plus.EntityFramework/EfCoreActiveTransactionProvider.cs
+46
-0
EfCoreBasedSecondaryOrmRegistrar.cs
src/Plus.EntityFramework/EfCoreBasedSecondaryOrmRegistrar.cs
+18
-0
DbContextExtensions.cs
src/Plus.EntityFramework/Extensions/DbContextExtensions.cs
+17
-0
EntityEntryExtensions.cs
src/Plus.EntityFramework/Extensions/EntityEntryExtensions.cs
+3
-0
QueryableExtensions.cs
src/Plus.EntityFramework/Extensions/QueryableExtensions.cs
+49
-0
IDbContextEntityFinder.cs
src/Plus.EntityFramework/IDbContextEntityFinder.cs
+14
-0
IDbContextProvider.cs
src/Plus.EntityFramework/IDbContextProvider.cs
+13
-0
IDbContextResolver.cs
src/Plus.EntityFramework/IDbContextResolver.cs
+13
-0
PlusEntityFrameworkModule.cs
src/Plus.EntityFramework/PlusEntityFrameworkModule.cs
+80
-0
PlusEntityMaterializerSource.cs
src/Plus.EntityFramework/PlusEntityMaterializerSource.cs
+84
-0
EfCoreAutoRepositoryTypes.cs
...EntityFramework/Repositories/EfCoreAutoRepositoryTypes.cs
+22
-0
EfCoreRepositoryBaseOfTEntity.cs
...tyFramework/Repositories/EfCoreRepositoryBaseOfTEntity.cs
+22
-0
EfCoreRepositoryBaseOfTEntityAndTPrimaryKey.cs
...positories/EfCoreRepositoryBaseOfTEntityAndTPrimaryKey.cs
+306
-0
EfCoreRepositoryExtensions.cs
...ntityFramework/Repositories/EfCoreRepositoryExtensions.cs
+32
-0
EfGenericRepositoryRegistrar.cs
...ityFramework/Repositories/EfGenericRepositoryRegistrar.cs
+104
-0
IEfGenericRepositoryRegistrar.cs
...tyFramework/Repositories/IEfGenericRepositoryRegistrar.cs
+14
-0
IRepositoryWithDbContext.cs
....EntityFramework/Repositories/IRepositoryWithDbContext.cs
+12
-0
SecondaryOrmRegistrarBase.cs
src/Plus.EntityFramework/SecondaryOrmRegistrarBase.cs
+68
-0
ActiveTransactionInfo.cs
src/Plus.EntityFramework/Uow/ActiveTransactionInfo.cs
+25
-0
DbContextEfCoreTransactionStrategy.cs
...EntityFramework/Uow/DbContextEfCoreTransactionStrategy.cs
+100
-0
EfCoreUnitOfWork.cs
src/Plus.EntityFramework/Uow/EfCoreUnitOfWork.cs
+170
-0
IEfCoreTransactionStrategy.cs
src/Plus.EntityFramework/Uow/IEfCoreTransactionStrategy.cs
+20
-0
UnitOfWorkDbContextProvider.cs
src/Plus.EntityFramework/Uow/UnitOfWorkDbContextProvider.cs
+24
-0
UnitOfWorkExtensions.cs
src/Plus.EntityFramework/Uow/UnitOfWorkExtensions.cs
+25
-0
IIocResolver.cs
src/Plus/Dependency/IIocResolver.cs
+8
-0
EntityTypeInfo.cs
src/Plus/Domain/Entities/EntityTypeInfo.cs
+20
-0
ProxyHelper.cs
src/Plus/Reflection/ProxyHelper.cs
+15
-0
ReflectionHelper.cs
src/Plus/Reflection/ReflectionHelper.cs
+2
-2
DisableDateTimeNormalizationAttribute.cs
src/Plus/Timing/DisableDateTimeNormalizationAttribute.cs
+12
-0
No files found.
src/Plus.EntityFramework/Configuration/IPlusDbContextConfigurer.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
namespace
Plus.EntityFramework.Configuration
{
/// <summary>
/// IPlusDbContextConfigurer
/// </summary>
/// <typeparam name="TDbContext"></typeparam>
public
interface
IPlusDbContextConfigurer
<
TDbContext
>
where
TDbContext
:
DbContext
{
void
Configure
(
PlusDbContextConfiguration
<
TDbContext
>
configuration
);
}
}
\ No newline at end of file
src/Plus.EntityFramework/Configuration/IPlusEfCoreConfiguration.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
System
;
namespace
Plus.EntityFramework.Configuration
{
/// <summary>
/// IPlusEfCoreConfiguration
/// </summary>
public
interface
IPlusEfCoreConfiguration
{
void
AddDbContext
<
TDbContext
>(
Action
<
PlusDbContextConfiguration
<
TDbContext
>>
action
)
where
TDbContext
:
DbContext
;
}
}
\ No newline at end of file
src/Plus.EntityFramework/Configuration/PlusDbContextConfiguration.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
System.Data.Common
;
namespace
Plus.EntityFramework.Configuration
{
/// <summary>
/// PlusDbContextConfiguration
/// </summary>
/// <typeparam name="TDbContext"></typeparam>
public
class
PlusDbContextConfiguration
<
TDbContext
>
where
TDbContext
:
DbContext
{
public
string
ConnectionString
{
get
;
internal
set
;
}
public
DbConnection
ExistingConnection
{
get
;
internal
set
;
}
public
DbContextOptionsBuilder
<
TDbContext
>
DbContextOptions
{
get
;
}
public
PlusDbContextConfiguration
(
string
connectionString
,
DbConnection
existingConnection
)
{
ConnectionString
=
connectionString
;
ExistingConnection
=
existingConnection
;
DbContextOptions
=
new
DbContextOptionsBuilder
<
TDbContext
>();
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/Configuration/PlusDbContextConfigurerAction.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
System
;
namespace
Plus.EntityFramework.Configuration
{
/// <summary>
/// PlusDbContextConfigurerAction
/// </summary>
/// <typeparam name="TDbContext"></typeparam>
public
class
PlusDbContextConfigurerAction
<
TDbContext
>
:
IPlusDbContextConfigurer
<
TDbContext
>
where
TDbContext
:
DbContext
{
public
Action
<
PlusDbContextConfiguration
<
TDbContext
>>
Action
{
get
;
set
;
}
public
PlusDbContextConfigurerAction
(
Action
<
PlusDbContextConfiguration
<
TDbContext
>>
action
)
{
Action
=
action
;
}
public
void
Configure
(
PlusDbContextConfiguration
<
TDbContext
>
configuration
)
{
Action
(
configuration
);
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/Configuration/PlusEfCoreConfiguration.cs
0 → 100644
View file @
707e93cb
using
Castle.MicroKernel.Registration
;
using
Microsoft.EntityFrameworkCore
;
using
Plus.Dependency
;
using
System
;
namespace
Plus.EntityFramework.Configuration
{
/// <summary>
/// PlusEfCoreConfiguration
/// </summary>
public
class
PlusEfCoreConfiguration
:
IPlusEfCoreConfiguration
{
private
readonly
IIocManager
_iocManager
;
public
PlusEfCoreConfiguration
(
IIocManager
iocManager
)
{
_iocManager
=
iocManager
;
}
public
void
AddDbContext
<
TDbContext
>(
Action
<
PlusDbContextConfiguration
<
TDbContext
>>
action
)
where
TDbContext
:
DbContext
{
_iocManager
.
IocContainer
.
Register
(
Component
.
For
<
IPlusDbContextConfigurer
<
TDbContext
>>().
Instance
(
new
PlusDbContextConfigurerAction
<
TDbContext
>(
action
)
).
IsDefault
()
);
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/DefaultDbContextResolver.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
Microsoft.EntityFrameworkCore.Metadata.Internal
;
using
Plus.Dependency
;
using
Plus.EntityFramework.Configuration
;
using
System
;
using
System.Data.Common
;
using
System.Linq
;
using
System.Reflection
;
namespace
Plus.EntityFramework
{
/// <summary>
/// DefaultDbContextResolver
/// </summary>
public
class
DefaultDbContextResolver
:
IDbContextResolver
,
ITransientDependency
{
private
static
readonly
MethodInfo
CreateOptionsMethod
=
typeof
(
DefaultDbContextResolver
).
GetMethod
(
"CreateOptions"
,
BindingFlags
.
NonPublic
|
BindingFlags
.
Instance
);
private
readonly
IIocResolver
_iocResolver
;
private
readonly
IDbContextTypeMatcher
_dbContextTypeMatcher
;
public
DefaultDbContextResolver
(
IIocResolver
iocResolver
,
IDbContextTypeMatcher
dbContextTypeMatcher
)
{
_iocResolver
=
iocResolver
;
_dbContextTypeMatcher
=
dbContextTypeMatcher
;
}
public
TDbContext
Resolve
<
TDbContext
>(
string
connectionString
,
DbConnection
existingConnection
)
where
TDbContext
:
DbContext
{
var
dbContextType
=
typeof
(
TDbContext
);
Type
concreteType
=
null
;
var
isAbstractDbContext
=
dbContextType
.
GetTypeInfo
().
IsAbstract
;
if
(
isAbstractDbContext
)
{
concreteType
=
_dbContextTypeMatcher
.
GetConcreteType
(
dbContextType
);
}
try
{
if
(
isAbstractDbContext
)
{
return
(
TDbContext
)
_iocResolver
.
Resolve
(
concreteType
);
}
return
_iocResolver
.
Resolve
<
TDbContext
>(
concreteType
);
}
catch
(
Castle
.
MicroKernel
.
Resolvers
.
DependencyResolverException
ex
)
{
var
hasOptions
=
isAbstractDbContext
?
HasOptions
(
concreteType
)
:
HasOptions
(
dbContextType
);
if
(!
hasOptions
)
{
throw
new
AggregateException
(
$"The parameter name of
{
dbContextType
.
Name
}
's constructor must be 'options'"
,
ex
);
}
throw
;
}
bool
HasOptions
(
Type
contextType
)
{
return
contextType
.
GetConstructors
().
Any
(
ctor
=>
{
var
parameters
=
ctor
.
GetParameters
();
return
parameters
.
Length
==
1
&&
parameters
.
FirstOrDefault
()?.
Name
==
"options"
;
});
}
}
private
object
CreateOptionsForType
(
Type
dbContextType
,
string
connectionString
,
DbConnection
existingConnection
)
{
return
CreateOptionsMethod
.
MakeGenericMethod
(
dbContextType
).
Invoke
(
this
,
new
object
[]
{
connectionString
,
existingConnection
});
}
protected
virtual
DbContextOptions
<
TDbContext
>
CreateOptions
<
TDbContext
>(
string
connectionString
,
DbConnection
existingConnection
)
where
TDbContext
:
DbContext
{
if
(
_iocResolver
.
IsRegistered
<
IPlusDbContextConfigurer
<
TDbContext
>>())
{
var
configuration
=
new
PlusDbContextConfiguration
<
TDbContext
>(
connectionString
,
existingConnection
);
ReplaceServices
(
configuration
);
using
(
var
configurer
=
_iocResolver
.
ResolveAsDisposable
<
IPlusDbContextConfigurer
<
TDbContext
>>())
{
configurer
.
Object
.
Configure
(
configuration
);
}
return
configuration
.
DbContextOptions
.
Options
;
}
if
(
_iocResolver
.
IsRegistered
<
DbContextOptions
<
TDbContext
>>())
{
return
_iocResolver
.
Resolve
<
DbContextOptions
<
TDbContext
>>();
}
throw
new
PlusException
(
$"Could not resolve DbContextOptions for
{
typeof
(
TDbContext
).
AssemblyQualifiedName
}
."
);
}
protected
virtual
void
ReplaceServices
<
TDbContext
>(
PlusDbContextConfiguration
<
TDbContext
>
configuration
)
where
TDbContext
:
DbContext
{
configuration
.
DbContextOptions
.
ReplaceService
<
IEntityMaterializerSource
,
PlusEntityMaterializerSource
>();
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/EfCoreActiveTransactionProvider.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
Microsoft.EntityFrameworkCore.Storage
;
using
Plus.Data
;
using
Plus.Dependency
;
using
System
;
using
System.Data
;
using
System.Reflection
;
namespace
Plus.EntityFramework
{
/// <summary>
/// EfCoreActiveTransactionProvider
/// </summary>
public
class
EfCoreActiveTransactionProvider
:
IActiveTransactionProvider
,
ITransientDependency
{
private
readonly
IIocResolver
_iocResolver
;
public
EfCoreActiveTransactionProvider
(
IIocResolver
iocResolver
)
{
_iocResolver
=
iocResolver
;
}
public
IDbTransaction
GetActiveTransaction
(
ActiveTransactionProviderArgs
args
)
{
return
GetDbContext
(
args
).
Database
.
CurrentTransaction
?.
GetDbTransaction
();
}
public
IDbConnection
GetActiveConnection
(
ActiveTransactionProviderArgs
args
)
{
return
GetDbContext
(
args
).
Database
.
GetDbConnection
();
}
private
DbContext
GetDbContext
(
ActiveTransactionProviderArgs
args
)
{
Type
dbContextProviderType
=
typeof
(
IDbContextProvider
<>).
MakeGenericType
((
Type
)
args
[
"ContextType"
]);
using
(
IDisposableDependencyObjectWrapper
dbContextProviderWrapper
=
_iocResolver
.
ResolveAsDisposable
(
dbContextProviderType
))
{
MethodInfo
method
=
dbContextProviderWrapper
.
Object
.
GetType
()
.
GetMethod
(
"GetDbContext"
);
return
(
DbContext
)
method
.
Invoke
(
dbContextProviderWrapper
.
Object
,
new
object
[
0
]);
}
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/EfCoreBasedSecondaryOrmRegistrar.cs
0 → 100644
View file @
707e93cb
using
System
;
namespace
Plus.EntityFramework
{
/// <summary>
/// EfCoreBasedSecondaryOrmRegistrar
/// </summary>
public
class
EfCoreBasedSecondaryOrmRegistrar
:
SecondaryOrmRegistrarBase
{
public
override
string
OrmContextKey
{
get
;
}
=
"EntityFrameworkCore"
;
public
EfCoreBasedSecondaryOrmRegistrar
(
Type
dbContextType
,
IDbContextEntityFinder
dbContextEntityFinder
)
:
base
(
dbContextType
,
dbContextEntityFinder
)
{
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/Extensions/DbContextExtensions.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
Microsoft.EntityFrameworkCore.Infrastructure
;
using
Microsoft.EntityFrameworkCore.Storage
;
namespace
Plus.EntityFramework.Extensions
{
/// <summary>
/// DbContextExtensions
/// </summary>
internal
static
class
DbContextExtensions
{
public
static
bool
HasRelationalTransactionManager
(
this
DbContext
dbContext
)
{
return
dbContext
.
Database
.
GetService
<
IDbContextTransactionManager
>()
is
IRelationalTransactionManager
;
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/Extensions/EntityEntryExtensions.cs
View file @
707e93cb
...
...
@@ -4,6 +4,9 @@ using System.Linq;
namespace
Plus.EntityFramework.Extensions
{
/// <summary>
/// EntityEntryExtensions
/// </summary>
public
static
class
EntityEntryExtensions
{
/// <summary>
...
...
src/Plus.EntityFramework/Extensions/QueryableExtensions.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
Microsoft.EntityFrameworkCore.Query
;
using
System
;
using
System.Linq
;
using
System.Linq.Expressions
;
namespace
Plus.EntityFramework.Extensions
{
/// <summary>
/// QueryableExtensions
/// </summary>
public
static
class
QueryableExtensions
{
public
static
IQueryable
<
T
>
IncludeIf
<
T
>(
this
IQueryable
<
T
>
source
,
bool
condition
,
string
path
)
where
T
:
class
{
return
condition
?
EntityFrameworkQueryableExtensions
.
Include
(
source
,
path
)
:
source
;
}
public
static
IQueryable
<
T
>
IncludeIf
<
T
,
TProperty
>(
this
IQueryable
<
T
>
source
,
bool
condition
,
Expression
<
Func
<
T
,
TProperty
>>
path
)
where
T
:
class
{
object
result
;
if
(!
condition
)
{
result
=
source
;
}
else
{
IQueryable
<
T
>
queryable
=
source
.
Include
(
path
);
result
=
queryable
;
}
return
(
IQueryable
<
T
>)
result
;
}
public
static
IQueryable
<
T
>
IncludeIf
<
T
>(
this
IQueryable
<
T
>
source
,
bool
condition
,
Func
<
IQueryable
<
T
>,
IIncludableQueryable
<
T
,
object
>>
include
)
where
T
:
class
{
object
result
;
if
(!
condition
)
{
result
=
source
;
}
else
{
IQueryable
<
T
>
queryable
=
include
(
source
);
result
=
queryable
;
}
return
(
IQueryable
<
T
>)
result
;
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/IDbContextEntityFinder.cs
0 → 100644
View file @
707e93cb
using
Plus.Domain.Entities
;
using
System
;
using
System.Collections.Generic
;
namespace
Plus.EntityFramework
{
/// <summary>
/// IDbContextEntityFinder
/// </summary>
public
interface
IDbContextEntityFinder
{
IEnumerable
<
EntityTypeInfo
>
GetEntityTypeInfos
(
Type
dbContextType
);
}
}
\ No newline at end of file
src/Plus.EntityFramework/IDbContextProvider.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
namespace
Plus.EntityFramework
{
/// <summary>
/// IDbContextProvider
/// </summary>
/// <typeparam name="TDbContext"></typeparam>
public
interface
IDbContextProvider
<
out
TDbContext
>
where
TDbContext
:
DbContext
{
TDbContext
GetDbContext
();
}
}
\ No newline at end of file
src/Plus.EntityFramework/IDbContextResolver.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
System.Data.Common
;
namespace
Plus.EntityFramework
{
/// <summary>
/// IDbContextResolver
/// </summary>
public
interface
IDbContextResolver
{
TDbContext
Resolve
<
TDbContext
>(
string
connectionString
,
DbConnection
existingConnection
)
where
TDbContext
:
DbContext
;
}
}
\ No newline at end of file
src/Plus.EntityFramework/PlusEntityFrameworkModule.cs
0 → 100644
View file @
707e93cb
using
Castle.MicroKernel.Registration
;
using
Plus.EntityFramework.Configuration
;
using
Plus.EntityFramework.Repositories
;
using
Plus.EntityFramework.Uow
;
using
Plus.Modules
;
using
Plus.Orm
;
using
Plus.Reflection
;
using
System
;
using
System.Reflection
;
namespace
Plus.EntityFramework
{
/// <summary>
/// EntityFramework 数据访问层
/// </summary>
[
DependsOn
(
typeof
(
PlusLeadershipModule
))]
public
class
PlusEntityFrameworkModule
:
PlusModule
{
private
readonly
ITypeFinder
_typeFinder
;
public
PlusEntityFrameworkModule
(
ITypeFinder
typeFinder
)
{
_typeFinder
=
typeFinder
;
}
public
override
void
PreInitialize
()
{
IocManager
.
Register
<
IPlusEfCoreConfiguration
,
PlusEfCoreConfiguration
>();
}
public
override
void
Initialize
()
{
IocManager
.
RegisterAssembly
(
typeof
(
PlusEntityFrameworkModule
).
GetAssembly
());
IocManager
.
IocContainer
.
Register
(
Component
.
For
(
typeof
(
IDbContextProvider
<>))
.
ImplementedBy
(
typeof
(
UnitOfWorkDbContextProvider
<>))
.
LifestyleTransient
()
);
RegisterGenericRepositoriesAndMatchDbContexes
();
}
private
void
RegisterGenericRepositoriesAndMatchDbContexes
()
{
var
dbContextTypes
=
_typeFinder
.
Find
(
type
=>
{
var
typeInfo
=
type
.
GetTypeInfo
();
return
typeInfo
.
IsPublic
&&
!
typeInfo
.
IsAbstract
&&
typeInfo
.
IsClass
&&
typeof
(
PlusDbContext
).
IsAssignableFrom
(
type
);
});
if
(
dbContextTypes
.
IsNullOrEmpty
())
{
Logger
.
Warn
(
"No class found derived from AbpDbContext."
);
return
;
}
foreach
(
var
dbContextType
in
dbContextTypes
)
{
Logger
.
Debug
(
"Registering DbContext: "
+
dbContextType
.
AssemblyQualifiedName
);
IocManager
.
Resolve
<
IEfGenericRepositoryRegistrar
>().
RegisterForDbContext
(
dbContextType
,
IocManager
,
EfCoreAutoRepositoryTypes
.
Default
);
IocManager
.
IocContainer
.
Register
(
Component
.
For
<
ISecondaryOrmRegistrar
>()
.
Named
(
Guid
.
NewGuid
().
ToString
(
"N"
))
.
Instance
(
new
EfCoreBasedSecondaryOrmRegistrar
(
dbContextType
,
IocManager
.
Resolve
<
IDbContextEntityFinder
>()))
.
LifestyleTransient
()
);
}
IocManager
.
Resolve
<
IDbContextTypeMatcher
>().
Populate
(
dbContextTypes
);
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/PlusEntityMaterializerSource.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore.Metadata
;
using
Microsoft.EntityFrameworkCore.Metadata.Internal
;
using
Plus.Reflection
;
using
Plus.Timing
;
using
System
;
using
System.Linq.Expressions
;
using
System.Reflection
;
namespace
Plus.EntityFramework
{
/// <summary>
/// PlusEntityMaterializerSource
/// </summary>
public
class
PlusEntityMaterializerSource
:
EntityMaterializerSource
{
private
static
readonly
MethodInfo
NormalizeDateTimeMethod
=
typeof
(
PlusEntityMaterializerSource
).
GetTypeInfo
().
GetMethod
(
nameof
(
NormalizeDateTime
),
BindingFlags
.
Static
|
BindingFlags
.
NonPublic
);
private
static
readonly
MethodInfo
NormalizeNullableDateTimeMethod
=
typeof
(
PlusEntityMaterializerSource
).
GetTypeInfo
().
GetMethod
(
nameof
(
NormalizeNullableDateTime
),
BindingFlags
.
Static
|
BindingFlags
.
NonPublic
);
public
override
Expression
CreateReadValueExpression
(
Expression
valueBuffer
,
Type
type
,
int
index
,
IPropertyBase
propertyBase
)
{
if
(
ShouldDisableDateTimeNormalization
(
propertyBase
))
{
return
base
.
CreateReadValueExpression
(
valueBuffer
,
type
,
index
,
propertyBase
);
}
if
(
type
==
typeof
(
DateTime
))
{
return
Expression
.
Call
(
NormalizeDateTimeMethod
,
base
.
CreateReadValueExpression
(
valueBuffer
,
type
,
index
,
propertyBase
)
);
}
if
(
type
==
typeof
(
DateTime
?))
{
return
Expression
.
Call
(
NormalizeNullableDateTimeMethod
,
base
.
CreateReadValueExpression
(
valueBuffer
,
type
,
index
,
propertyBase
)
);
}
return
base
.
CreateReadValueExpression
(
valueBuffer
,
type
,
index
,
propertyBase
);
}
private
static
DateTime
NormalizeDateTime
(
DateTime
value
)
{
return
value
;
}
private
static
DateTime
?
NormalizeNullableDateTime
(
DateTime
?
value
)
{
if
(
value
==
null
)
{
return
null
;
}
return
value
.
Value
;
}
private
static
bool
ShouldDisableDateTimeNormalization
(
IPropertyBase
propertyBase
)
{
if
(
propertyBase
==
null
)
{
return
false
;
}
if
(
propertyBase
.
PropertyInfo
==
null
)
{
return
false
;
}
if
(
propertyBase
.
PropertyInfo
.
IsDefined
(
typeof
(
DisableDateTimeNormalizationAttribute
),
true
))
{
return
true
;
}
propertyBase
.
TryGetMemberInfo
(
false
,
false
,
out
var
memberInfo
,
out
_
);
return
ReflectionHelper
.
GetSingleAttributeOfMemberOrDeclaringTypeOrDefault
<
DisableDateTimeNormalizationAttribute
>(
memberInfo
)
!=
null
;
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/Repositories/EfCoreAutoRepositoryTypes.cs
0 → 100644
View file @
707e93cb
using
Plus.Domain.Repositories
;
namespace
Plus.EntityFramework.Repositories
{
/// <summary>
/// EfCoreAutoRepositoryTypes
/// </summary>
public
static
class
EfCoreAutoRepositoryTypes
{
public
static
AutoRepositoryTypesAttribute
Default
{
get
;
}
static
EfCoreAutoRepositoryTypes
()
{
Default
=
new
AutoRepositoryTypesAttribute
(
typeof
(
IRepository
<>),
typeof
(
IRepository
<,>),
typeof
(
EfCoreRepositoryBase
<,>),
typeof
(
EfCoreRepositoryBase
<,,>)
);
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/Repositories/EfCoreRepositoryBaseOfTEntity.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
Plus.Domain.Entities
;
using
Plus.Domain.Repositories
;
namespace
Plus.EntityFramework.Repositories
{
/// <summary>
/// EfCoreRepositoryBase
/// </summary>
/// <typeparam name="TDbContext"></typeparam>
/// <typeparam name="TEntity"></typeparam>
public
class
EfCoreRepositoryBase
<
TDbContext
,
TEntity
>
:
EfCoreRepositoryBase
<
TDbContext
,
TEntity
,
int
>,
IRepository
<
TEntity
>
where
TEntity
:
class
,
IEntity
<
int
>
where
TDbContext
:
DbContext
{
public
EfCoreRepositoryBase
(
IDbContextProvider
<
TDbContext
>
dbContextProvider
)
:
base
(
dbContextProvider
)
{
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/Repositories/EfCoreRepositoryBaseOfTEntityAndTPrimaryKey.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
Plus.Data
;
using
Plus.Domain.Entities
;
using
Plus.Domain.Repositories
;
using
System
;
using
System.Collections.Generic
;
using
System.Data
;
using
System.Data.Common
;
using
System.Linq
;
using
System.Linq.Expressions
;
using
System.Threading
;
using
System.Threading.Tasks
;
namespace
Plus.EntityFramework.Repositories
{
/// <summary>
/// Implements IRepository for Entity Framework.
/// </summary>
/// <typeparam name="TDbContext">DbContext which contains <typeparamref name="TEntity"/>.</typeparam>
/// <typeparam name="TEntity">Type of the Entity for this repository</typeparam>
/// <typeparam name="TPrimaryKey">Primary key of the entity</typeparam>
public
class
EfCoreRepositoryBase
<
TDbContext
,
TEntity
,
TPrimaryKey
>
:
PlusRepositoryBase
<
TEntity
,
TPrimaryKey
>,
ISupportsExplicitLoading
<
TEntity
,
TPrimaryKey
>,
IRepositoryWithDbContext
where
TEntity
:
class
,
IEntity
<
TPrimaryKey
>
where
TDbContext
:
DbContext
{
/// <summary>
/// Gets EF DbContext object.
/// </summary>
public
virtual
TDbContext
Context
=>
_dbContextProvider
.
GetDbContext
();
/// <summary>
/// Gets DbSet for given entity.
/// </summary>
public
virtual
DbSet
<
TEntity
>
Table
=>
Context
.
Set
<
TEntity
>();
public
virtual
DbTransaction
Transaction
{
get
{
return
(
DbTransaction
)
TransactionProvider
?.
GetActiveTransaction
(
new
ActiveTransactionProviderArgs
{
{
"ContextType"
,
typeof
(
TDbContext
)
}
});
}
}
public
virtual
DbConnection
Connection
{
get
{
var
connection
=
Context
.
Database
.
GetDbConnection
();
if
(
connection
.
State
!=
ConnectionState
.
Open
)
{
connection
.
Open
();
}
return
connection
;
}
}
public
IActiveTransactionProvider
TransactionProvider
{
private
get
;
set
;
}
private
readonly
IDbContextProvider
<
TDbContext
>
_dbContextProvider
;
/// <summary>
/// Constructor
/// </summary>
/// <param name="dbContextProvider"></param>
public
EfCoreRepositoryBase
(
IDbContextProvider
<
TDbContext
>
dbContextProvider
)
{
_dbContextProvider
=
dbContextProvider
;
}
public
override
IQueryable
<
TEntity
>
GetAll
()
{
return
GetAllIncluding
();
}
public
override
IQueryable
<
TEntity
>
GetAllIncluding
(
params
Expression
<
Func
<
TEntity
,
object
>>[]
propertySelectors
)
{
var
query
=
Table
.
AsQueryable
();
if
(!
propertySelectors
.
IsNullOrEmpty
())
{
foreach
(
var
propertySelector
in
propertySelectors
)
{
query
=
query
.
Include
(
propertySelector
);
}
}
return
query
;
}
public
override
async
Task
<
List
<
TEntity
>>
GetAllListAsync
()
{
return
await
GetAll
().
ToListAsync
();
}
public
override
async
Task
<
List
<
TEntity
>>
GetAllListAsync
(
Expression
<
Func
<
TEntity
,
bool
>>
predicate
)
{
return
await
GetAll
().
Where
(
predicate
).
ToListAsync
();
}
public
override
async
Task
<
TEntity
>
SingleAsync
(
Expression
<
Func
<
TEntity
,
bool
>>
predicate
)
{
return
await
GetAll
().
SingleAsync
(
predicate
);
}
public
override
async
Task
<
TEntity
>
FirstOrDefaultAsync
(
TPrimaryKey
id
)
{
return
await
GetAll
().
FirstOrDefaultAsync
(
CreateEqualityExpressionForId
(
id
));
}
public
override
async
Task
<
TEntity
>
FirstOrDefaultAsync
(
Expression
<
Func
<
TEntity
,
bool
>>
predicate
)
{
return
await
GetAll
().
FirstOrDefaultAsync
(
predicate
);
}
public
override
TEntity
Insert
(
TEntity
entity
)
{
return
Table
.
Add
(
entity
).
Entity
;
}
public
override
Task
<
TEntity
>
InsertAsync
(
TEntity
entity
)
{
return
Task
.
FromResult
(
Insert
(
entity
));
}
public
override
TPrimaryKey
InsertAndGetId
(
TEntity
entity
)
{
entity
=
Insert
(
entity
);
if
(
MayHaveTemporaryKey
(
entity
)
||
entity
.
IsTransient
())
{
Context
.
SaveChanges
();
}
return
entity
.
Id
;
}
public
override
async
Task
<
TPrimaryKey
>
InsertAndGetIdAsync
(
TEntity
entity
)
{
entity
=
await
InsertAsync
(
entity
);
if
(
MayHaveTemporaryKey
(
entity
)
||
entity
.
IsTransient
())
{
await
Context
.
SaveChangesAsync
();
}
return
entity
.
Id
;
}
public
override
TPrimaryKey
InsertOrUpdateAndGetId
(
TEntity
entity
)
{
entity
=
InsertOrUpdate
(
entity
);
if
(
MayHaveTemporaryKey
(
entity
)
||
entity
.
IsTransient
())
{
Context
.
SaveChanges
();
}
return
entity
.
Id
;
}
public
override
async
Task
<
TPrimaryKey
>
InsertOrUpdateAndGetIdAsync
(
TEntity
entity
)
{
entity
=
await
InsertOrUpdateAsync
(
entity
);
if
(
MayHaveTemporaryKey
(
entity
)
||
entity
.
IsTransient
())
{
await
Context
.
SaveChangesAsync
();
}
return
entity
.
Id
;
}
public
override
TEntity
Update
(
TEntity
entity
)
{
AttachIfNot
(
entity
);
Context
.
Entry
(
entity
).
State
=
EntityState
.
Modified
;
return
entity
;
}
public
override
Task
<
TEntity
>
UpdateAsync
(
TEntity
entity
)
{
entity
=
Update
(
entity
);
return
Task
.
FromResult
(
entity
);
}
public
override
void
Delete
(
TEntity
entity
)
{
AttachIfNot
(
entity
);
Table
.
Remove
(
entity
);
}
public
override
void
Delete
(
TPrimaryKey
id
)
{
var
entity
=
GetFromChangeTrackerOrNull
(
id
);
if
(
entity
!=
null
)
{
Delete
(
entity
);
return
;
}
entity
=
FirstOrDefault
(
id
);
if
(
entity
!=
null
)
{
Delete
(
entity
);
return
;
}
//Could not found the entity, do nothing.
}
public
override
async
Task
<
int
>
CountAsync
()
{
return
await
GetAll
().
CountAsync
();
}
public
override
async
Task
<
int
>
CountAsync
(
Expression
<
Func
<
TEntity
,
bool
>>
predicate
)
{
return
await
GetAll
().
Where
(
predicate
).
CountAsync
();
}
public
override
async
Task
<
long
>
LongCountAsync
()
{
return
await
GetAll
().
LongCountAsync
();
}
public
override
async
Task
<
long
>
LongCountAsync
(
Expression
<
Func
<
TEntity
,
bool
>>
predicate
)
{
return
await
GetAll
().
Where
(
predicate
).
LongCountAsync
();
}
protected
virtual
void
AttachIfNot
(
TEntity
entity
)
{
var
entry
=
Context
.
ChangeTracker
.
Entries
().
FirstOrDefault
(
ent
=>
ent
.
Entity
==
entity
);
if
(
entry
!=
null
)
{
return
;
}
Table
.
Attach
(
entity
);
}
public
DbContext
GetDbContext
()
{
return
Context
;
}
public
Task
EnsureCollectionLoadedAsync
<
TProperty
>(
TEntity
entity
,
Expression
<
Func
<
TEntity
,
IEnumerable
<
TProperty
>>>
collectionExpression
,
CancellationToken
cancellationToken
)
where
TProperty
:
class
{
return
Context
.
Entry
(
entity
).
Collection
(
collectionExpression
).
LoadAsync
(
cancellationToken
);
}
public
Task
EnsurePropertyLoadedAsync
<
TProperty
>(
TEntity
entity
,
Expression
<
Func
<
TEntity
,
TProperty
>>
propertyExpression
,
CancellationToken
cancellationToken
)
where
TProperty
:
class
{
return
Context
.
Entry
(
entity
).
Reference
(
propertyExpression
).
LoadAsync
(
cancellationToken
);
}
private
TEntity
GetFromChangeTrackerOrNull
(
TPrimaryKey
id
)
{
var
entry
=
Context
.
ChangeTracker
.
Entries
()
.
FirstOrDefault
(
ent
=>
ent
.
Entity
is
TEntity
&&
EqualityComparer
<
TPrimaryKey
>.
Default
.
Equals
(
id
,
(
ent
.
Entity
as
TEntity
).
Id
)
);
return
entry
?.
Entity
as
TEntity
;
}
private
static
bool
MayHaveTemporaryKey
(
TEntity
entity
)
{
if
(
typeof
(
TPrimaryKey
)
==
typeof
(
byte
))
{
return
true
;
}
if
(
typeof
(
TPrimaryKey
)
==
typeof
(
int
))
{
return
Convert
.
ToInt32
(
entity
.
Id
)
<=
0
;
}
if
(
typeof
(
TPrimaryKey
)
==
typeof
(
long
))
{
return
Convert
.
ToInt64
(
entity
.
Id
)
<=
0
;
}
return
false
;
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/Repositories/EfCoreRepositoryExtensions.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
Plus.Domain.Entities
;
using
Plus.Domain.Repositories
;
using
Plus.Reflection
;
using
System
;
namespace
Plus.EntityFramework.Repositories
{
/// <summary>
/// EfCoreRepositoryExtensions
/// </summary>
public
static
class
EfCoreRepositoryExtensions
{
public
static
DbContext
GetDbContext
<
TEntity
,
TPrimaryKey
>(
this
IRepository
<
TEntity
,
TPrimaryKey
>
repository
)
where
TEntity
:
class
,
IEntity
<
TPrimaryKey
>
{
var
repositoryWithDbContext
=
ProxyHelper
.
UnProxy
(
repository
)
as
IRepositoryWithDbContext
;
if
(
repositoryWithDbContext
!=
null
)
{
return
repositoryWithDbContext
.
GetDbContext
();
}
throw
new
ArgumentException
(
"Given repository does not implement IRepositoryWithDbContext"
,
nameof
(
repository
));
}
public
static
void
DetachFromDbContext
<
TEntity
,
TPrimaryKey
>(
this
IRepository
<
TEntity
,
TPrimaryKey
>
repository
,
TEntity
entity
)
where
TEntity
:
class
,
IEntity
<
TPrimaryKey
>
{
repository
.
GetDbContext
().
Entry
(
entity
).
State
=
EntityState
.
Detached
;
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/Repositories/EfGenericRepositoryRegistrar.cs
0 → 100644
View file @
707e93cb
using
Castle.Core.Logging
;
using
Castle.MicroKernel.Registration
;
using
Plus.Dependency
;
using
Plus.Domain.Entities
;
using
Plus.Domain.Repositories
;
using
System
;
using
System.Reflection
;
namespace
Plus.EntityFramework.Repositories
{
/// <summary>
/// EfGenericRepositoryRegistrar
/// </summary>
public
class
EfGenericRepositoryRegistrar
:
IEfGenericRepositoryRegistrar
,
ITransientDependency
{
public
ILogger
Logger
{
get
;
set
;
}
private
readonly
IDbContextEntityFinder
_dbContextEntityFinder
;
public
EfGenericRepositoryRegistrar
(
IDbContextEntityFinder
dbContextEntityFinder
)
{
_dbContextEntityFinder
=
dbContextEntityFinder
;
Logger
=
NullLogger
.
Instance
;
}
public
void
RegisterForDbContext
(
Type
dbContextType
,
IIocManager
iocManager
,
AutoRepositoryTypesAttribute
defaultAutoRepositoryTypesAttribute
)
{
var
autoRepositoryAttr
=
dbContextType
.
GetTypeInfo
().
GetSingleAttributeOrNull
<
AutoRepositoryTypesAttribute
>()
??
defaultAutoRepositoryTypesAttribute
;
RegisterForDbContext
(
dbContextType
,
iocManager
,
autoRepositoryAttr
.
RepositoryInterface
,
autoRepositoryAttr
.
RepositoryInterfaceWithPrimaryKey
,
autoRepositoryAttr
.
RepositoryImplementation
,
autoRepositoryAttr
.
RepositoryImplementationWithPrimaryKey
);
if
(
autoRepositoryAttr
.
WithDefaultRepositoryInterfaces
)
{
RegisterForDbContext
(
dbContextType
,
iocManager
,
defaultAutoRepositoryTypesAttribute
.
RepositoryInterface
,
defaultAutoRepositoryTypesAttribute
.
RepositoryInterfaceWithPrimaryKey
,
autoRepositoryAttr
.
RepositoryImplementation
,
autoRepositoryAttr
.
RepositoryImplementationWithPrimaryKey
);
}
}
private
void
RegisterForDbContext
(
Type
dbContextType
,
IIocManager
iocManager
,
Type
repositoryInterface
,
Type
repositoryInterfaceWithPrimaryKey
,
Type
repositoryImplementation
,
Type
repositoryImplementationWithPrimaryKey
)
{
foreach
(
var
entityTypeInfo
in
_dbContextEntityFinder
.
GetEntityTypeInfos
(
dbContextType
))
{
var
primaryKeyType
=
EntityHelper
.
GetPrimaryKeyType
(
entityTypeInfo
.
EntityType
);
if
(
primaryKeyType
==
typeof
(
int
))
{
var
genericRepositoryType
=
repositoryInterface
.
MakeGenericType
(
entityTypeInfo
.
EntityType
);
if
(!
iocManager
.
IsRegistered
(
genericRepositoryType
))
{
var
implType
=
repositoryImplementation
.
GetGenericArguments
().
Length
==
1
?
repositoryImplementation
.
MakeGenericType
(
entityTypeInfo
.
EntityType
)
:
repositoryImplementation
.
MakeGenericType
(
entityTypeInfo
.
DeclaringType
,
entityTypeInfo
.
EntityType
);
iocManager
.
IocContainer
.
Register
(
Component
.
For
(
genericRepositoryType
)
.
ImplementedBy
(
implType
)
.
Named
(
Guid
.
NewGuid
().
ToString
(
"N"
))
.
LifestyleTransient
()
);
}
}
var
genericRepositoryTypeWithPrimaryKey
=
repositoryInterfaceWithPrimaryKey
.
MakeGenericType
(
entityTypeInfo
.
EntityType
,
primaryKeyType
);
if
(!
iocManager
.
IsRegistered
(
genericRepositoryTypeWithPrimaryKey
))
{
var
implType
=
repositoryImplementationWithPrimaryKey
.
GetGenericArguments
().
Length
==
2
?
repositoryImplementationWithPrimaryKey
.
MakeGenericType
(
entityTypeInfo
.
EntityType
,
primaryKeyType
)
:
repositoryImplementationWithPrimaryKey
.
MakeGenericType
(
entityTypeInfo
.
DeclaringType
,
entityTypeInfo
.
EntityType
,
primaryKeyType
);
iocManager
.
IocContainer
.
Register
(
Component
.
For
(
genericRepositoryTypeWithPrimaryKey
)
.
ImplementedBy
(
implType
)
.
Named
(
Guid
.
NewGuid
().
ToString
(
"N"
))
.
LifestyleTransient
()
);
}
}
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/Repositories/IEfGenericRepositoryRegistrar.cs
0 → 100644
View file @
707e93cb
using
Plus.Dependency
;
using
Plus.Domain.Repositories
;
using
System
;
namespace
Plus.EntityFramework.Repositories
{
/// <summary>
/// IEfGenericRepositoryRegistrar
/// </summary>
public
interface
IEfGenericRepositoryRegistrar
{
void
RegisterForDbContext
(
Type
dbContextType
,
IIocManager
iocManager
,
AutoRepositoryTypesAttribute
defaultAutoRepositoryTypesAttribute
);
}
}
\ No newline at end of file
src/Plus.EntityFramework/Repositories/IRepositoryWithDbContext.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
namespace
Plus.EntityFramework.Repositories
{
/// <summary>
/// IRepositoryWithDbContext
/// </summary>
public
interface
IRepositoryWithDbContext
{
DbContext
GetDbContext
();
}
}
\ No newline at end of file
src/Plus.EntityFramework/SecondaryOrmRegistrarBase.cs
0 → 100644
View file @
707e93cb
using
Plus.Dependency
;
using
Plus.Domain.Entities
;
using
Plus.Domain.Repositories
;
using
Plus.Orm
;
using
System
;
using
System.Reflection
;
namespace
Plus.EntityFramework
{
/// <summary>
/// SecondaryOrmRegistrarBase
/// </summary>
public
abstract
class
SecondaryOrmRegistrarBase
:
ISecondaryOrmRegistrar
{
private
readonly
IDbContextEntityFinder
_dbContextEntityFinder
;
private
readonly
Type
_dbContextType
;
public
abstract
string
OrmContextKey
{
get
;
}
protected
SecondaryOrmRegistrarBase
(
Type
dbContextType
,
IDbContextEntityFinder
dbContextEntityFinder
)
{
_dbContextType
=
dbContextType
;
_dbContextEntityFinder
=
dbContextEntityFinder
;
}
public
virtual
void
RegisterRepositories
(
IIocManager
iocManager
,
AutoRepositoryTypesAttribute
defaultRepositoryTypes
)
{
AutoRepositoryTypesAttribute
autoRepositoryAttr
=
_dbContextType
.
GetTypeInfo
().
GetSingleAttributeOrNull
<
AutoRepositoryTypesAttribute
>()
??
defaultRepositoryTypes
;
foreach
(
EntityTypeInfo
entityTypeInfo
in
_dbContextEntityFinder
.
GetEntityTypeInfos
(
_dbContextType
))
{
Type
primaryKeyType
=
EntityHelper
.
GetPrimaryKeyType
(
entityTypeInfo
.
EntityType
);
if
(
primaryKeyType
==
typeof
(
int
))
{
Type
genericRepositoryType
=
autoRepositoryAttr
.
RepositoryInterface
.
MakeGenericType
(
entityTypeInfo
.
EntityType
);
if
(!
iocManager
.
IsRegistered
(
genericRepositoryType
))
{
Type
implType
=
autoRepositoryAttr
.
RepositoryImplementation
.
GetTypeInfo
().
GetGenericArguments
().
Length
==
1
?
autoRepositoryAttr
.
RepositoryImplementation
.
MakeGenericType
(
entityTypeInfo
.
EntityType
)
:
autoRepositoryAttr
.
RepositoryImplementation
.
MakeGenericType
(
entityTypeInfo
.
DeclaringType
,
entityTypeInfo
.
EntityType
);
iocManager
.
Register
(
genericRepositoryType
,
implType
,
DependencyLifeStyle
.
Transient
);
}
}
Type
genericRepositoryTypeWithPrimaryKey
=
autoRepositoryAttr
.
RepositoryInterfaceWithPrimaryKey
.
MakeGenericType
(
entityTypeInfo
.
EntityType
,
primaryKeyType
);
if
(!
iocManager
.
IsRegistered
(
genericRepositoryTypeWithPrimaryKey
))
{
Type
implType
=
autoRepositoryAttr
.
RepositoryImplementationWithPrimaryKey
.
GetTypeInfo
().
GetGenericArguments
().
Length
==
2
?
autoRepositoryAttr
.
RepositoryImplementationWithPrimaryKey
.
MakeGenericType
(
entityTypeInfo
.
EntityType
,
primaryKeyType
)
:
autoRepositoryAttr
.
RepositoryImplementationWithPrimaryKey
.
MakeGenericType
(
entityTypeInfo
.
DeclaringType
,
entityTypeInfo
.
EntityType
,
primaryKeyType
);
iocManager
.
Register
(
genericRepositoryTypeWithPrimaryKey
,
implType
,
DependencyLifeStyle
.
Transient
);
}
}
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/Uow/ActiveTransactionInfo.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
Microsoft.EntityFrameworkCore.Storage
;
using
System.Collections.Generic
;
namespace
Plus.EntityFramework.Uow
{
/// <summary>
/// ActiveTransactionInfo
/// </summary>
public
class
ActiveTransactionInfo
{
public
IDbContextTransaction
DbContextTransaction
{
get
;
}
public
DbContext
StarterDbContext
{
get
;
}
public
List
<
DbContext
>
AttendedDbContexts
{
get
;
}
public
ActiveTransactionInfo
(
IDbContextTransaction
dbContextTransaction
,
DbContext
starterDbContext
)
{
DbContextTransaction
=
dbContextTransaction
;
StarterDbContext
=
starterDbContext
;
AttendedDbContexts
=
new
List
<
DbContext
>();
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/Uow/DbContextEfCoreTransactionStrategy.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
Microsoft.EntityFrameworkCore.Storage
;
using
Plus.Dependency
;
using
Plus.Domain.Uow
;
using
Plus.EntityFramework.Extensions
;
using
System.Collections.Generic
;
using
System.Transactions
;
namespace
Plus.EntityFramework.Uow
{
/// <summary>
/// DbContextEfCoreTransactionStrategy
/// </summary>
public
class
DbContextEfCoreTransactionStrategy
:
IEfCoreTransactionStrategy
,
ITransientDependency
{
protected
UnitOfWorkOptions
Options
{
get
;
private
set
;
}
protected
IDictionary
<
string
,
ActiveTransactionInfo
>
ActiveTransactions
{
get
;
}
public
DbContextEfCoreTransactionStrategy
()
{
ActiveTransactions
=
new
Dictionary
<
string
,
ActiveTransactionInfo
>();
}
public
void
InitOptions
(
UnitOfWorkOptions
options
)
{
Options
=
options
;
}
public
DbContext
CreateDbContext
<
TDbContext
>(
string
connectionString
,
IDbContextResolver
dbContextResolver
)
where
TDbContext
:
DbContext
{
DbContext
dbContext
;
var
activeTransaction
=
ActiveTransactions
.
GetOrDefault
(
connectionString
);
if
(
activeTransaction
==
null
)
{
dbContext
=
dbContextResolver
.
Resolve
<
TDbContext
>(
connectionString
,
null
);
var
dbtransaction
=
dbContext
.
Database
.
BeginTransaction
((
Options
.
IsolationLevel
??
IsolationLevel
.
ReadUncommitted
).
ToSystemDataIsolationLevel
());
activeTransaction
=
new
ActiveTransactionInfo
(
dbtransaction
,
dbContext
);
ActiveTransactions
[
connectionString
]
=
activeTransaction
;
}
else
{
dbContext
=
dbContextResolver
.
Resolve
<
TDbContext
>(
connectionString
,
activeTransaction
.
DbContextTransaction
.
GetDbTransaction
().
Connection
);
if
(
dbContext
.
HasRelationalTransactionManager
())
{
dbContext
.
Database
.
UseTransaction
(
activeTransaction
.
DbContextTransaction
.
GetDbTransaction
());
}
else
{
dbContext
.
Database
.
BeginTransaction
();
}
activeTransaction
.
AttendedDbContexts
.
Add
(
dbContext
);
}
return
dbContext
;
}
public
void
Commit
()
{
foreach
(
var
activeTransaction
in
ActiveTransactions
.
Values
)
{
activeTransaction
.
DbContextTransaction
.
Commit
();
foreach
(
var
dbContext
in
activeTransaction
.
AttendedDbContexts
)
{
if
(
dbContext
.
HasRelationalTransactionManager
())
{
continue
;
//Relational databases use the shared transaction
}
dbContext
.
Database
.
CommitTransaction
();
}
}
}
public
void
Dispose
(
IIocResolver
iocResolver
)
{
foreach
(
var
activeTransaction
in
ActiveTransactions
.
Values
)
{
activeTransaction
.
DbContextTransaction
.
Dispose
();
foreach
(
var
attendedDbContext
in
activeTransaction
.
AttendedDbContexts
)
{
iocResolver
.
Release
(
attendedDbContext
);
}
iocResolver
.
Release
(
activeTransaction
.
StarterDbContext
);
}
ActiveTransactions
.
Clear
();
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/Uow/EfCoreUnitOfWork.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
Plus.Dependency
;
using
Plus.Domain.Uow
;
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Threading.Tasks
;
namespace
Plus.EntityFramework.Uow
{
/// <summary>
/// EfCoreUnitOfWork
/// </summary>
public
class
EfCoreUnitOfWork
:
UnitOfWorkBase
,
ITransientDependency
{
protected
IDictionary
<
string
,
DbContext
>
ActiveDbContexts
{
get
;
}
protected
IIocResolver
IocResolver
{
get
;
}
private
readonly
IDbContextResolver
_dbContextResolver
;
private
readonly
IDbContextTypeMatcher
_dbContextTypeMatcher
;
private
readonly
IEfCoreTransactionStrategy
_transactionStrategy
;
public
EfCoreUnitOfWork
(
IIocResolver
iocResolver
,
IConnectionStringResolver
connectionStringResolver
,
IUnitOfWorkFilterExecuter
filterExecuter
,
IDbContextResolver
dbContextResolver
,
IUnitOfWorkDefaultOptions
defaultOptions
,
IDbContextTypeMatcher
dbContextTypeMatcher
,
IEfCoreTransactionStrategy
transactionStrategy
)
:
base
(
connectionStringResolver
,
defaultOptions
,
filterExecuter
)
{
IocResolver
=
iocResolver
;
_dbContextResolver
=
dbContextResolver
;
_dbContextTypeMatcher
=
dbContextTypeMatcher
;
_transactionStrategy
=
transactionStrategy
;
ActiveDbContexts
=
new
Dictionary
<
string
,
DbContext
>();
}
protected
override
void
BeginUow
()
{
if
(
Options
.
IsTransactional
==
true
)
{
_transactionStrategy
.
InitOptions
(
Options
);
}
}
public
override
void
SaveChanges
()
{
foreach
(
var
dbContext
in
GetAllActiveDbContexts
())
{
SaveChangesInDbContext
(
dbContext
);
}
}
public
override
async
Task
SaveChangesAsync
()
{
foreach
(
var
dbContext
in
GetAllActiveDbContexts
())
{
await
SaveChangesInDbContextAsync
(
dbContext
);
}
}
protected
override
void
CompleteUow
()
{
SaveChanges
();
CommitTransaction
();
}
protected
override
async
Task
CompleteUowAsync
()
{
await
SaveChangesAsync
();
CommitTransaction
();
}
private
void
CommitTransaction
()
{
if
(
Options
.
IsTransactional
==
true
)
{
_transactionStrategy
.
Commit
();
}
}
public
IReadOnlyList
<
DbContext
>
GetAllActiveDbContexts
()
{
return
ActiveDbContexts
.
Values
.
ToImmutableList
();
}
public
virtual
TDbContext
GetOrCreateDbContext
<
TDbContext
>(
string
name
=
null
)
where
TDbContext
:
DbContext
{
var
concreteDbContextType
=
_dbContextTypeMatcher
.
GetConcreteType
(
typeof
(
TDbContext
));
var
connectionStringResolveArgs
=
new
ConnectionStringResolveArgs
{
[
"DbContextType"
]
=
typeof
(
TDbContext
),
[
"DbContextConcreteType"
]
=
concreteDbContextType
};
var
connectionString
=
ResolveConnectionString
(
connectionStringResolveArgs
);
var
dbContextKey
=
concreteDbContextType
.
FullName
+
"#"
+
connectionString
;
if
(
name
!=
null
)
{
dbContextKey
+=
"#"
+
name
;
}
if
(!
ActiveDbContexts
.
TryGetValue
(
dbContextKey
,
out
DbContext
dbContext
))
{
if
(
Options
.
IsTransactional
==
true
)
{
dbContext
=
_transactionStrategy
.
CreateDbContext
<
TDbContext
>(
connectionString
,
_dbContextResolver
);
}
else
{
dbContext
=
_dbContextResolver
.
Resolve
<
TDbContext
>(
connectionString
,
null
);
}
if
(
Options
.
Timeout
.
HasValue
&&
dbContext
.
Database
.
IsRelational
()
&&
!
dbContext
.
Database
.
GetCommandTimeout
().
HasValue
)
{
dbContext
.
Database
.
SetCommandTimeout
(
Options
.
Timeout
.
Value
.
TotalSeconds
.
To
<
int
>());
}
//TODO: Object materialize event
//TODO: Apply current filters to this dbcontext
ActiveDbContexts
[
dbContextKey
]
=
dbContext
;
}
return
(
TDbContext
)
dbContext
;
}
protected
override
void
DisposeUow
()
{
if
(
Options
.
IsTransactional
==
true
)
{
_transactionStrategy
.
Dispose
(
IocResolver
);
}
else
{
foreach
(
var
context
in
GetAllActiveDbContexts
())
{
Release
(
context
);
}
}
ActiveDbContexts
.
Clear
();
}
protected
virtual
void
SaveChangesInDbContext
(
DbContext
dbContext
)
{
dbContext
.
SaveChanges
();
}
protected
virtual
async
Task
SaveChangesInDbContextAsync
(
DbContext
dbContext
)
{
await
dbContext
.
SaveChangesAsync
();
}
protected
virtual
void
Release
(
DbContext
dbContext
)
{
dbContext
.
Dispose
();
IocResolver
.
Release
(
dbContext
);
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/Uow/IEfCoreTransactionStrategy.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
Plus.Dependency
;
using
Plus.Domain.Uow
;
namespace
Plus.EntityFramework.Uow
{
/// <summary>
/// IEfCoreTransactionStrategy
/// </summary>
public
interface
IEfCoreTransactionStrategy
{
void
InitOptions
(
UnitOfWorkOptions
options
);
DbContext
CreateDbContext
<
TDbContext
>(
string
connectionString
,
IDbContextResolver
dbContextResolver
)
where
TDbContext
:
DbContext
;
void
Commit
();
void
Dispose
(
IIocResolver
iocResolver
);
}
}
\ No newline at end of file
src/Plus.EntityFramework/Uow/UnitOfWorkDbContextProvider.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
Plus.Domain.Uow
;
namespace
Plus.EntityFramework.Uow
{
/// <summary>
/// UnitOfWorkDbContextProvider
/// </summary>
/// <typeparam name="TDbContext"></typeparam>
public
class
UnitOfWorkDbContextProvider
<
TDbContext
>
:
IDbContextProvider
<
TDbContext
>
where
TDbContext
:
DbContext
{
private
readonly
ICurrentUnitOfWorkProvider
_currentUnitOfWorkProvider
;
public
UnitOfWorkDbContextProvider
(
ICurrentUnitOfWorkProvider
currentUnitOfWorkProvider
)
{
_currentUnitOfWorkProvider
=
currentUnitOfWorkProvider
;
}
public
TDbContext
GetDbContext
()
{
return
_currentUnitOfWorkProvider
.
Current
.
GetDbContext
<
TDbContext
>();
}
}
}
\ No newline at end of file
src/Plus.EntityFramework/Uow/UnitOfWorkExtensions.cs
0 → 100644
View file @
707e93cb
using
Microsoft.EntityFrameworkCore
;
using
Plus.Domain.Uow
;
using
System
;
namespace
Plus.EntityFramework.Uow
{
/// <summary>
/// UnitOfWorkExtensions
/// </summary>
public
static
class
UnitOfWorkExtensions
{
public
static
TDbContext
GetDbContext
<
TDbContext
>(
this
IActiveUnitOfWork
unitOfWork
,
string
name
=
null
)
where
TDbContext
:
DbContext
{
if
(
unitOfWork
==
null
)
{
throw
new
ArgumentNullException
(
"unitOfWork"
);
}
if
(!(
unitOfWork
is
EfCoreUnitOfWork
))
{
throw
new
ArgumentException
(
"unitOfWork is not type of "
+
typeof
(
EfCoreUnitOfWork
).
FullName
,
"unitOfWork"
);
}
return
(
unitOfWork
as
EfCoreUnitOfWork
).
GetOrCreateDbContext
<
TDbContext
>(
name
);
}
}
}
\ No newline at end of file
src/Plus/Dependency/IIocResolver.cs
View file @
707e93cb
...
...
@@ -28,6 +28,14 @@ namespace Plus.Dependency
/// <returns></returns>
T
[]
ResolveAll
<
T
>();
/// <summary>
/// 从IOC容器中获取对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="type"></param>
/// <returns></returns>
T
Resolve
<
T
>(
Type
type
);
/// <summary>
/// 是否注册了给定的类型
/// </summary>
...
...
src/Plus/Domain/Entities/EntityTypeInfo.cs
0 → 100644
View file @
707e93cb
using
System
;
namespace
Plus.Domain.Entities
{
/// <summary>
/// EntityTypeInfo
/// </summary>
public
class
EntityTypeInfo
{
public
Type
EntityType
{
get
;
private
set
;
}
public
Type
DeclaringType
{
get
;
private
set
;
}
public
EntityTypeInfo
(
Type
entityType
,
Type
declaringType
)
{
EntityType
=
entityType
;
DeclaringType
=
declaringType
;
}
}
}
\ No newline at end of file
src/Plus/Reflection/ProxyHelper.cs
0 → 100644
View file @
707e93cb
using
Castle.DynamicProxy
;
namespace
Plus.Reflection
{
/// <summary>
/// ProxyHelper
/// </summary>
public
class
ProxyHelper
{
public
static
object
UnProxy
(
object
obj
)
{
return
ProxyUtil
.
GetUnproxiedInstance
(
obj
);
}
}
}
\ No newline at end of file
src/Plus/Reflection/ReflectionHelper.cs
View file @
707e93cb
...
...
@@ -8,7 +8,7 @@ namespace Plus.Reflection
/// <summary>
/// 反射帮助类
/// </summary>
internal
static
class
ReflectionHelper
public
static
class
ReflectionHelper
{
/// <summary>
/// Checks whether <paramref name="givenType"/> implements/inherits <paramref name="genericType"/>.
...
...
@@ -130,7 +130,7 @@ namespace Plus.Reflection
/// <param name="memberInfo">MemberInfo</param>
/// <param name="defaultValue">Default value (null as default)</param>
/// <param name="inherit">Inherit attribute from base classes</param>
public
static
TAttribute
GetSingleAttributeOfMemberOrDeclaringTypeOrDefault
<
TAttribute
>(
MemberInfo
memberInfo
,
TAttribute
defaultValue
=
default
(
TAttribute
)
,
bool
inherit
=
true
)
public
static
TAttribute
GetSingleAttributeOfMemberOrDeclaringTypeOrDefault
<
TAttribute
>(
MemberInfo
memberInfo
,
TAttribute
defaultValue
=
default
,
bool
inherit
=
true
)
where
TAttribute
:
class
{
return
memberInfo
.
GetCustomAttributes
(
true
).
OfType
<
TAttribute
>().
FirstOrDefault
()
...
...
src/Plus/Timing/DisableDateTimeNormalizationAttribute.cs
0 → 100644
View file @
707e93cb
using
System
;
namespace
Plus.Timing
{
/// <summary>
/// DisableDateTimeNormalizationAttribute
/// </summary>
[
AttributeUsage
(
AttributeTargets
.
Class
|
AttributeTargets
.
Property
|
AttributeTargets
.
Parameter
)]
public
class
DisableDateTimeNormalizationAttribute
:
Attribute
{
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment