Skip to content

Commit 7a80ede

Browse files
committed
call sp as selectable; tests
1 parent 6e702cb commit 7a80ede

File tree

4 files changed

+828
-2
lines changed

4 files changed

+828
-2
lines changed
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/*
2+
* The contents of this file are subject to the Initial
3+
* Developer's Public License Version 1.0 (the "License");
4+
* you may not use this file except in compliance with the
5+
* License. You may obtain a copy of the License at
6+
* https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt.
7+
*
8+
* Software distributed under the License is distributed on
9+
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
10+
* express or implied. See the License for the specific
11+
* language governing rights and limitations under the License.
12+
*
13+
* All Rights Reserved.
14+
*/
15+
16+
//$Authors = Jiri Cincura (jiri@cincura.net)
17+
18+
using System;
19+
using System.Linq;
20+
using System.Threading.Tasks;
21+
using Microsoft.EntityFrameworkCore;
22+
using NUnit.Framework;
23+
24+
namespace FirebirdSql.EntityFrameworkCore.Firebird.Tests.EndToEnd;
25+
26+
public class DeleteTestsUsingSP : EntityFrameworkCoreTestsBase
27+
{
28+
class DeleteContext : FbTestDbContext
29+
{
30+
public DeleteContext(string connectionString)
31+
: base(connectionString)
32+
{ }
33+
34+
protected override void OnTestModelCreating(ModelBuilder modelBuilder)
35+
{
36+
base.OnTestModelCreating(modelBuilder);
37+
38+
var insertEntityConf = modelBuilder.Entity<DeleteEntity>();
39+
insertEntityConf.Property(x => x.Id).HasColumnName("ID");
40+
insertEntityConf.Property(x => x.Name).HasColumnName("NAME");
41+
insertEntityConf.ToTable("TEST_DELETE_USP");
42+
modelBuilder.Entity<DeleteEntity>().DeleteUsingStoredProcedure("SP_TEST_DELETE",
43+
storedProcedureBuilder =>
44+
{
45+
storedProcedureBuilder.HasOriginalValueParameter(x => x.Id);
46+
storedProcedureBuilder.HasRowsAffectedResultColumn();
47+
});
48+
}
49+
}
50+
class DeleteEntity
51+
{
52+
public int Id { get; set; }
53+
public string Name { get; set; }
54+
}
55+
[Test]
56+
public async Task Delete()
57+
{
58+
await using (var db = await GetDbContext<DeleteContext>())
59+
{
60+
await db.Database.ExecuteSqlRawAsync("create table test_delete_usp (id int primary key, name varchar(20))");
61+
await db.Database.ExecuteSqlRawAsync("insert into test_delete_usp values (65, 'test')");
62+
await db.Database.ExecuteSqlRawAsync("insert into test_delete_usp values (66, 'test')");
63+
await db.Database.ExecuteSqlRawAsync("insert into test_delete_usp values (67, 'test')");
64+
var sp = """
65+
create or alter procedure sp_test_delete (
66+
pid integer)
67+
returns (rowcount integer)
68+
as
69+
begin
70+
delete from test_delete_usp where id = :pid;
71+
rowcount = row_count;
72+
suspend;
73+
end
74+
""";
75+
await db.Database.ExecuteSqlRawAsync(sp);
76+
var entity = new DeleteEntity() { Id = 66 };
77+
var entry = db.Attach(entity);
78+
entry.State = EntityState.Deleted;
79+
await db.SaveChangesAsync();
80+
var values = await db.Set<DeleteEntity>()
81+
.FromSqlRaw("select * from test_delete_usp")
82+
.AsNoTracking()
83+
.OrderBy(x => x.Id)
84+
.ToListAsync();
85+
Assert.AreEqual(2, values.Count());
86+
Assert.AreEqual(65, values[0].Id);
87+
Assert.AreEqual(67, values[1].Id);
88+
}
89+
}
90+
91+
class ConcurrencyDeleteContext : FbTestDbContext
92+
{
93+
public ConcurrencyDeleteContext(string connectionString)
94+
: base(connectionString)
95+
{ }
96+
97+
protected override void OnTestModelCreating(ModelBuilder modelBuilder)
98+
{
99+
base.OnTestModelCreating(modelBuilder);
100+
101+
var insertEntityConf = modelBuilder.Entity<ConcurrencyDeleteEntity>();
102+
insertEntityConf.Property(x => x.Id).HasColumnName("ID");
103+
insertEntityConf.Property(x => x.Name).HasColumnName("NAME");
104+
insertEntityConf.Property(x => x.Stamp).HasColumnName("STAMP")
105+
.IsRowVersion();
106+
insertEntityConf.ToTable("TEST_DELETE_CONCURRENCY_USP");
107+
modelBuilder.Entity<ConcurrencyDeleteEntity>().DeleteUsingStoredProcedure("SP_TEST_DELETE_CONCURRENCY",
108+
storedProcedureBuilder =>
109+
{
110+
storedProcedureBuilder.HasOriginalValueParameter(x => x.Id);
111+
storedProcedureBuilder.HasOriginalValueParameter(x => x.Stamp);
112+
storedProcedureBuilder.HasRowsAffectedResultColumn();
113+
});
114+
}
115+
}
116+
class ConcurrencyDeleteEntity
117+
{
118+
public int Id { get; set; }
119+
public string Name { get; set; }
120+
public DateTime Stamp { get; set; }
121+
}
122+
[Test]
123+
public async Task ConcurrencyDelete()
124+
{
125+
await using (var db = await GetDbContext<ConcurrencyDeleteContext>())
126+
{
127+
await db.Database.ExecuteSqlRawAsync("create table test_delete_concurrency_usp (id int primary key, name varchar(20), stamp timestamp)");
128+
await db.Database.ExecuteSqlRawAsync("insert into test_delete_concurrency_usp values (65, 'test', current_timestamp)");
129+
await db.Database.ExecuteSqlRawAsync("insert into test_delete_concurrency_usp values (66, 'test', current_timestamp)");
130+
await db.Database.ExecuteSqlRawAsync("insert into test_delete_concurrency_usp values (67, 'test', current_timestamp)");
131+
var sp = """
132+
create or alter procedure sp_test_delete_concurrency (
133+
pid integer,
134+
pstamp timestamp)
135+
returns (rowcount integer)
136+
as
137+
begin
138+
delete from test_delete_concurrency_usp where id = :pid and stamp = :pstamp;
139+
rowcount = row_count;
140+
if (rowcount > 0) then suspend;
141+
end
142+
""";
143+
await db.Database.ExecuteSqlRawAsync(sp);
144+
var entity = new ConcurrencyDeleteEntity() { Id = 66, Stamp = new DateTime(1970, 1, 1) };
145+
var entry = db.Attach(entity);
146+
entry.State = EntityState.Deleted;
147+
Assert.ThrowsAsync<DbUpdateConcurrencyException>(() => db.SaveChangesAsync());
148+
}
149+
}
150+
}

0 commit comments

Comments
 (0)