Skip to content

Commit 6075dac

Browse files
Merge pull request #39 from Lempireqc/master
save
2 parents 3829346 + 48c6342 commit 6075dac

File tree

7 files changed

+160
-77
lines changed

7 files changed

+160
-77
lines changed

EntityFrameworkExtras.EFCore.sln

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Global
2323
EntityFrameworkExtras.Tests.Shared\EntityFrameworkExtras.Tests.Shared.projitems*{59943b99-772a-47e4-aa70-6d758312c00c}*SharedItemsImports = 4
2424
EntityFrameworkExtras.Shared\EntityFrameworkExtras.Shared.projitems*{770fa648-fa98-455d-8bf7-9832c9ede9c6}*SharedItemsImports = 13
2525
EntityFrameworkExtras.Tests.Shared\EntityFrameworkExtras.Tests.Shared.projitems*{8189d203-89f3-4d02-b028-f76ce37c9fdb}*SharedItemsImports = 13
26+
EntityFrameworkExtras.Shared\EntityFrameworkExtras.Shared.projitems*{94101b83-cd6b-4f8a-9ab9-93a0d3371d07}*SharedItemsImports = 5
2627
EndGlobalSection
2728
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2829
Debug|Any CPU = Debug|Any CPU

EntityFrameworkExtras.EFCore3.lab/Program.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class Program
66
{
77
static void Main(string[] args)
88
{
9+
Request_storeProcedure_Transaction.Execute();
910
Request_TimeOut.Execute();
1011
}
1112
}

EntityFrameworkExtras.EFCore3.lab/Request_TimeOut.cs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Data;
44
using System.Linq;
5+
using System.Reflection;
56
using System.Text;
67
using System.Transactions;
78
using EntityFrameworkExtras.EFCore;
@@ -69,10 +70,7 @@ CREATE PROCEDURE [dbo].[PROC_Get_EntitySimple]
6970
AS
7071
BEGIN
7172
WAITFOR DELAY '00:00:08';
72-
update EntitySimples
73-
Set ColumnInt = @ParameterID ;
74-
75-
Set @ParameterInt = @ParameterID +1
73+
select * from EntitySimples ;
7674
END
7775
";
7876
commande.ExecuteNonQuery();
@@ -81,15 +79,16 @@ update EntitySimples
8179
}
8280

8381
// TEST
84-
using (var context = new EntityContext())
85-
{
86-
var proc_Get_EntitySimple = new Proc_Get_EntitySimple() { ParameterID = 2 };
87-
context.Database.SetCommandTimeout(5);
88-
context.Database.ExecuteStoredProcedure(proc_Get_EntitySimple);
82+
using (var ctx = new EntityContext())
83+
{
8984

85+
var proc_Get_EntitySimple = new Proc_Get_EntitySimple() { ParameterID = 2 };
86+
ctx.Database.SetCommandTimeout(5);
87+
9088

91-
var t = context.Database.ExecuteStoredProcedure<EntitySimple>(proc_Get_EntitySimple);
9289

90+
var t = ctx.Database.ExecuteStoredProcedure<EntitySimple>(proc_Get_EntitySimple);
91+
ctx.Database.ExecuteStoredProcedure(proc_Get_EntitySimple);
9392
// var list = context.EntitySimples.ToList();
9493
}
9594
}

EntityFrameworkExtras.EFCore3.lab/Request_storeProcedure_Transaction.cs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,23 +126,32 @@ update EntitySimples
126126
using (var context = new EntityContext())
127127
{
128128
var proc_Get_EntitySimple = new Proc_Get_EntitySimple2() { ParameterID = 2 };
129+
var transaction = context.Database.BeginTransaction();
130+
context.Database.ExecuteStoredProcedure<EntitySimple>(proc_Get_EntitySimple);
131+
132+
133+
transaction.Rollback();
134+
var lisa = context.EntitySimples.ToList();
135+
136+
137+
var list = context.EntitySimples.ToList();
138+
}
139+
140+
using (var context = new EntityContext())
141+
{
142+
var proc_Get_EntitySimple = new Proc_Get_EntitySimple2() { ParameterID = 2 };
143+
129144

130145
using (var tran = new TransactionScope())
131146
{
132147
context.Database.ExecuteStoredProcedure<EntitySimple>(proc_Get_EntitySimple);
133148
}
134-
135-
var transaction = context.Database.BeginTransaction();
136-
context.Database.ExecuteStoredProcedure<EntitySimple>(proc_Get_EntitySimple);
137-
138-
transaction.Rollback();
139-
140149
var list = context.EntitySimples.ToList();
141150
}
142151

143152
using (var context = new EntityContext())
144153
{
145-
var proc_Get_EntitySimple = new Proc_Get_EntitySimple() { ParameterID = 2 };
154+
var proc_Get_EntitySimple = new Proc_Get_EntitySimple2() { ParameterID = 2 };
146155
using (var tran = new TransactionScope())
147156
{
148157
context.Database.ExecuteStoredProcedure<EntitySimple>(proc_Get_EntitySimple);

EntityFrameworkExtras.Shared/DatabaseExtensions.EFCore3x.cs

Lines changed: 126 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Threading.Tasks;
99
using Microsoft.EntityFrameworkCore;
1010
using Microsoft.EntityFrameworkCore.Infrastructure;
11+
using Microsoft.EntityFrameworkCore.Metadata;
1112
using Microsoft.EntityFrameworkCore.Storage;
1213

1314
namespace EntityFrameworkExtras.EFCore
@@ -64,58 +65,83 @@ public static async Task ExecuteStoredProcedureAsync(this DatabaseFacade databas
6465
/// <param name="database">The database to execute against.</param>
6566
/// <param name="storedProcedure">The stored procedure to execute.</param>
6667
/// <returns></returns>
67-
public static IEnumerable<T> ExecuteStoredProcedure<T>(this DatabaseFacade database, object storedProcedure)
68-
{
69-
if (storedProcedure == null)
70-
throw new ArgumentNullException("storedProcedure");
68+
public static IEnumerable<T> ExecuteStoredProcedure<T>(this DatabaseFacade database, object storedProcedure) where T : class
69+
{
70+
var contextField = database.GetType().GetField("_context", BindingFlags.Instance | BindingFlags.NonPublic);
71+
72+
var context = (DbContext)contextField.GetValue(database);
73+
74+
var entityType = FindModelEntityType(context, typeof(T));
75+
76+
if (entityType == null)
77+
{
78+
return database.InternalExecuteStoredProcedure<T>(storedProcedure);
79+
}
7180

81+
if (storedProcedure == null)
82+
throw new ArgumentNullException("storedProcedure");
7283

73-
List<T> result = new List<T>();
7484
var info = StoredProcedureParser.BuildStoredProcedureInfo(storedProcedure);
7585

86+
List<T> result = context.Set<T>().FromSqlRaw(info.Sql, info.SqlParameters).AsNoTracking().ToList();
7687

77-
// from : https://github.com/Fodsuk/EntityFrameworkExtras/pull/23/commits/dce354304aa9a95750f7d2559d1b002444ac46f7
78-
using (var command = database.GetDbConnection().CreateCommand())
79-
{
80-
command.CommandText = info.Sql;
88+
SetOutputParameterValues(info.SqlParameters, storedProcedure);
89+
90+
return result;
91+
}
92+
93+
internal static IEnumerable<T> InternalExecuteStoredProcedure<T>(this DatabaseFacade database, object storedProcedure)
94+
{
95+
if (storedProcedure == null)
96+
throw new ArgumentNullException("storedProcedure");
97+
98+
99+
List<T> result = new List<T>();
100+
var info = StoredProcedureParser.BuildStoredProcedureInfo(storedProcedure);
101+
102+
103+
// from : https://github.com/Fodsuk/EntityFrameworkExtras/pull/23/commits/dce354304aa9a95750f7d2559d1b002444ac46f7
104+
using (var command = database.GetDbConnection().CreateCommand())
105+
{
106+
command.CommandText = info.Sql;
81107
int? commandTimeout = database.GetCommandTimeout();
82-
if (commandTimeout.HasValue)
83-
{
84-
command.CommandTimeout = commandTimeout.Value;
85-
}
86-
command.CommandType = CommandType.Text;
87-
command.Parameters.AddRange(info.SqlParameters);
108+
if (commandTimeout.HasValue)
109+
{
110+
command.CommandTimeout = commandTimeout.Value;
111+
}
112+
command.CommandType = CommandType.Text;
113+
command.Parameters.AddRange(info.SqlParameters);
88114
command.Transaction = database.CurrentTransaction?.GetDbTransaction();
89-
database.OpenConnection();
90-
91-
using (var resultReader = command.ExecuteReader())
92-
{
93-
T obj = default(T);
94-
95-
while (resultReader.Read())
96-
{
97-
obj = Activator.CreateInstance<T>();
98-
foreach (PropertyInfo prop in obj.GetType().GetProperties())
99-
{
100-
var val = GetValue(resultReader, prop.Name);
101-
if (!object.Equals(val, DBNull.Value))
102-
{
103-
prop.SetValue(obj, val, null);
104-
}
105-
}
106-
107-
result.Add(obj);
108-
}
109-
}
115+
database.OpenConnection();
110116

111-
}
117+
using (var resultReader = command.ExecuteReader())
118+
{
119+
T obj = default(T);
112120

113-
SetOutputParameterValues(info.SqlParameters, storedProcedure);
121+
while (resultReader.Read())
122+
{
123+
obj = Activator.CreateInstance<T>();
124+
foreach (PropertyInfo prop in obj.GetType().GetProperties())
125+
{
126+
var val = GetValue(resultReader, prop.Name);
127+
if (!object.Equals(val, DBNull.Value))
128+
{
129+
prop.SetValue(obj, val, null);
130+
}
131+
}
114132

115-
return result;
116-
}
133+
result.Add(obj);
134+
}
135+
}
117136

118-
/// <summary>
137+
}
138+
139+
SetOutputParameterValues(info.SqlParameters, storedProcedure);
140+
141+
return result;
142+
}
143+
144+
/// <summary>
119145
/// Executes the specified stored procedure against a database asynchronously
120146
/// and returns an enumerable of T representing the data returned.
121147
/// </summary>
@@ -124,7 +150,32 @@ public static IEnumerable<T> ExecuteStoredProcedure<T>(this DatabaseFacade datab
124150
/// <param name="storedProcedure">The stored procedure to execute.</param>
125151
/// <param name="cancellationToken">The cancellation token.</param>
126152
/// <returns></returns>
127-
public static async Task<IEnumerable<T>> ExecuteStoredProcedureAsync<T>(this DatabaseFacade database, object storedProcedure, CancellationToken cancellationToken = default)
153+
public static async Task<IEnumerable<T>> ExecuteStoredProcedureAsync<T>(this DatabaseFacade database, object storedProcedure, CancellationToken cancellationToken = default) where T : class
154+
{
155+
var contextField = database.GetType().GetField("_context", BindingFlags.Instance | BindingFlags.NonPublic);
156+
157+
var context = (DbContext)contextField.GetValue(database);
158+
159+
var entityType = FindModelEntityType(context, typeof(T));
160+
161+
if (entityType == null)
162+
{
163+
return await database.InternalExecuteStoredProcedureAsync<T>(storedProcedure).ConfigureAwait(false);
164+
}
165+
166+
if (storedProcedure == null)
167+
throw new ArgumentNullException("storedProcedure");
168+
169+
var info = StoredProcedureParser.BuildStoredProcedureInfo(storedProcedure);
170+
171+
List<T> result = await context.Set<T>().FromSqlRaw(info.Sql, info.SqlParameters).AsNoTracking().ToListAsync(cancellationToken).ConfigureAwait(false);
172+
173+
SetOutputParameterValues(info.SqlParameters, storedProcedure);
174+
175+
return result;
176+
}
177+
178+
internal static async Task<IEnumerable<T>> InternalExecuteStoredProcedureAsync<T>(this DatabaseFacade database, object storedProcedure, CancellationToken cancellationToken = default)
128179
{
129180
if (storedProcedure == null)
130181
throw new ArgumentNullException("storedProcedure");
@@ -138,11 +189,11 @@ public static async Task<IEnumerable<T>> ExecuteStoredProcedureAsync<T>(this Dat
138189
using (var command = database.GetDbConnection().CreateCommand())
139190
{
140191
command.CommandText = info.Sql;
141-
int? commandTimeout = database.GetCommandTimeout();
142-
if (commandTimeout.HasValue)
143-
{
144-
command.CommandTimeout = commandTimeout.Value;
145-
}
192+
int? commandTimeout = database.GetCommandTimeout();
193+
if (commandTimeout.HasValue)
194+
{
195+
command.CommandTimeout = commandTimeout.Value;
196+
}
146197
command.CommandType = CommandType.Text;
147198
command.Parameters.AddRange(info.SqlParameters);
148199
command.Transaction = database.CurrentTransaction?.GetDbTransaction();
@@ -175,15 +226,15 @@ public static async Task<IEnumerable<T>> ExecuteStoredProcedureAsync<T>(this Dat
175226
return result;
176227
}
177228

178-
/// <summary>
179-
/// Executes the specified stored procedure against a database
180-
/// and returns the first or default value
181-
/// </summary>
182-
/// <typeparam name="T">Type of the data returned from the stored procedure.</typeparam>
183-
/// <param name="database">The database to execute against.</param>
184-
/// <param name="storedProcedure">The stored procedure to execute.</param>
185-
/// <returns></returns>
186-
public static T ExecuteStoredProcedureFirstOrDefault<T>(this DatabaseFacade database, object storedProcedure)
229+
/// <summary>
230+
/// Executes the specified stored procedure against a database
231+
/// and returns the first or default value
232+
/// </summary>
233+
/// <typeparam name="T">Type of the data returned from the stored procedure.</typeparam>
234+
/// <param name="database">The database to execute against.</param>
235+
/// <param name="storedProcedure">The stored procedure to execute.</param>
236+
/// <returns></returns>
237+
public static T ExecuteStoredProcedureFirstOrDefault<T>(this DatabaseFacade database, object storedProcedure) where T : class
187238
{
188239
return database.ExecuteStoredProcedure<T>(storedProcedure).FirstOrDefault();
189240
}
@@ -197,12 +248,30 @@ public static T ExecuteStoredProcedureFirstOrDefault<T>(this DatabaseFacade data
197248
/// <param name="storedProcedure">The stored procedure to execute.</param>
198249
/// <param name="cancellationToken">The cancellation token.</param>
199250
/// <returns></returns>
200-
public static async Task<T> ExecuteStoredProcedureFirstOrDefaultAsync<T>(this DatabaseFacade database, object storedProcedure, CancellationToken cancellationToken = default)
251+
public static async Task<T> ExecuteStoredProcedureFirstOrDefaultAsync<T>(this DatabaseFacade database, object storedProcedure, CancellationToken cancellationToken = default) where T : class
201252
{
202253
var executed = await database.ExecuteStoredProcedureAsync<T>(storedProcedure, cancellationToken).ConfigureAwait(false);
203254

204255
return executed.FirstOrDefault();
205256
}
257+
258+
internal static IEntityType FindModelEntityType(this DbContext @this, Type type)
259+
{
260+
var entityType = @this.Model.FindEntityType(type);
261+
262+
if (entityType == null)
263+
{
264+
var baseType = type;
265+
266+
while (baseType != null && entityType == null)
267+
{
268+
entityType = @this.Model.FindEntityType(baseType);
269+
baseType = baseType.BaseType;
270+
}
271+
}
272+
273+
return entityType;
274+
}
206275
}
207276
}
208277
#endif

EntityFrameworkExtras.Tests.Shared/Integration/DatabaseIntegrationTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ public void ExecuteStoredProcedure(object storedProcedure)
4040
context.Database.ExecuteStoredProcedure(storedProcedure);
4141
}
4242

43-
public IEnumerable<T> ExecuteStoredProcedure<T>(object storedProcedure)
43+
public IEnumerable<T> ExecuteStoredProcedure<T>(object storedProcedure) where T : class
4444
{
4545
return context.Database.ExecuteStoredProcedure<T>(storedProcedure);
4646
}
4747

48-
public T ExecuteStoredProcedureSingle<T>(object storedProcedure)
48+
public T ExecuteStoredProcedureSingle<T>(object storedProcedure) where T : class
4949
{
5050
return context.Database.ExecuteStoredProcedure<T>(storedProcedure).FirstOrDefault();
5151
}

EntityFrameworkExtras.sln

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkExtras.EF5.N
4848
EndProject
4949
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkExtras.EF6.Net40", "EntityFrameworkExtras.EF6.Net40\EntityFrameworkExtras.EF6.Net40.csproj", "{7ED1D61C-9396-4663-952D-D2F7DAD19B18}"
5050
EndProject
51-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Z.EntityFrameworkExtras.Lab.EFCore30", "EntityFrameworkExtras.EFCore3.lab\Z.EntityFrameworkExtras.Lab.EFCore30.csproj", "{F213770C-7433-44F6-A44E-EC9E3A304BDC}"
51+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Z.EntityFrameworkExtras.Lab.EFCore30", "EntityFrameworkExtras.EFCore3.lab\Z.EntityFrameworkExtras.Lab.EFCore30.csproj", "{F213770C-7433-44F6-A44E-EC9E3A304BDC}"
5252
EndProject
5353
Global
5454
GlobalSection(SharedMSBuildProjectFiles) = preSolution
@@ -62,7 +62,11 @@ Global
6262
EntityFrameworkExtras.Shared\EntityFrameworkExtras.Shared.projitems*{7ed1d61c-9396-4663-952d-d2f7dad19b19}*SharedItemsImports = 4
6363
EntityFrameworkExtras.Tests.Shared\EntityFrameworkExtras.Tests.Shared.projitems*{8189d203-89f3-4d02-b028-f76ce37c9fdb}*SharedItemsImports = 13
6464
EntityFrameworkExtras.Tests.Shared\EntityFrameworkExtras.Tests.Shared.projitems*{8522b7eb-3d2d-4e43-ba3d-3f16095b8efb}*SharedItemsImports = 4
65+
EntityFrameworkExtras.Shared\EntityFrameworkExtras.Shared.projitems*{8a995513-92c8-4e00-8c99-48bd56496f89}*SharedItemsImports = 5
66+
EntityFrameworkExtras.Shared\EntityFrameworkExtras.Shared.projitems*{909f9fc3-3384-467b-9a7d-1b2328080ba8}*SharedItemsImports = 5
67+
EntityFrameworkExtras.Shared\EntityFrameworkExtras.Shared.projitems*{992957e5-4e42-4e90-b510-2c3e3ca56b25}*SharedItemsImports = 5
6568
EntityFrameworkExtras.Tests.Shared\EntityFrameworkExtras.Tests.Shared.projitems*{b0c9b99b-0c3c-4e72-85d7-12bcd185c067}*SharedItemsImports = 4
69+
EntityFrameworkExtras.Shared\EntityFrameworkExtras.Shared.projitems*{c4c0a992-318d-4b77-b151-69e18b789a52}*SharedItemsImports = 5
6670
EndGlobalSection
6771
GlobalSection(SolutionConfigurationPlatforms) = preSolution
6872
Debug|Any CPU = Debug|Any CPU

0 commit comments

Comments
 (0)