Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit d08157b

Browse files
committed
Fix Microsoft.Data.SQLite tests
1 parent 82cb548 commit d08157b

File tree

11 files changed

+189
-49
lines changed

11 files changed

+189
-49
lines changed

src/ServiceStack.OrmLite.Sqlite.Data/SqliteOrmLiteDialectProvider.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1+
using System;
12
using System.Data;
23
using Microsoft.Data.Sqlite;
4+
using ServiceStack.OrmLite.Sqlite.Converters;
35

46
namespace ServiceStack.OrmLite.Sqlite
57
{
68
public class SqliteOrmLiteDialectProvider : SqliteOrmLiteDialectProviderBase
79
{
8-
public static SqliteOrmLiteDialectProvider Instance = new SqliteOrmLiteDialectProvider();
10+
public static SqliteOrmLiteDialectProvider Instance = new();
11+
12+
public SqliteOrmLiteDialectProvider()
13+
{
14+
base.RegisterConverter<DateTime>(new SqliteDataDateTimeConverter());
15+
base.RegisterConverter<Guid>(new SqliteDataGuidConverter());
16+
}
917

1018
protected override IDbConnection CreateConnection(string connectionString)
1119
{

src/ServiceStack.OrmLite.Sqlite/Converters/SqliteDateTimeConverter.cs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public override object GetValue(IDataReader reader, int columnIndex, object[] va
8181
/// <summary>
8282
/// New behavior from using System.Data.SQLite.Core
8383
/// </summary>
84-
public class SqliteSystemDataDateTimeConverter : SqliteNativeDateTimeConverter
84+
public class SqliteCoreDateTimeConverter : SqliteNativeDateTimeConverter
8585
{
8686
public override object ToDbValue(Type fieldType, object value)
8787
{
@@ -142,6 +142,29 @@ public override object GetValue(IDataReader reader, int columnIndex, object[] va
142142
}
143143
}
144144

145+
public class SqliteDataDateTimeConverter : SqliteCoreDateTimeConverter
146+
{
147+
public override object FromDbValue(Type fieldType, object value)
148+
{
149+
var dateTime = (DateTime)value;
150+
151+
if (DateStyle == DateTimeKind.Utc)
152+
{
153+
//.NET Core returns correct Local time but as Unspecified so change to Local and Convert to UTC
154+
dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc); // don't convert
155+
}
156+
157+
if (DateStyle == DateTimeKind.Local && dateTime.Kind != DateTimeKind.Local)
158+
{
159+
dateTime = dateTime.Kind == DateTimeKind.Utc
160+
? dateTime.ToLocalTime()
161+
: DateTime.SpecifyKind(dateTime, DateTimeKind.Local);
162+
}
163+
164+
return dateTime;
165+
}
166+
}
167+
145168
public class SqliteWindowsDateTimeConverter : SqliteNativeDateTimeConverter
146169
{
147170
public override object FromDbValue(Type fieldType, object value)

src/ServiceStack.OrmLite.Sqlite/Converters/SqliteGuidConverter.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,55 @@ public override object GetValue(IDataReader reader, int columnIndex, object[] va
3333
return reader.GetGuid(columnIndex);
3434
}
3535
}
36+
37+
public class SqliteDataGuidConverter : GuidConverter
38+
{
39+
public override string ColumnDefinition => "CHAR(36)";
40+
41+
public override string ToQuotedString(Type fieldType, object value)
42+
{
43+
var guid = (Guid)value;
44+
var bytes = guid.ToByteArray();
45+
SwapEndian(bytes);
46+
var p = BitConverter.ToString(bytes).Replace("-","");
47+
var fmt = "'" + p.Substring(0,8) + "-"
48+
+ p.Substring(8,4) + "-"
49+
+ p.Substring(12,4) + "-"
50+
+ p.Substring(16,4) + "-"
51+
+ p.Substring(20) + "'";
52+
return fmt;
53+
}
54+
55+
public static void SwapEndian(byte[] guid)
56+
{
57+
_ = guid ?? throw new ArgumentNullException(nameof(guid));
58+
Swap(guid, 0, 3);
59+
Swap(guid, 1, 2);
60+
Swap(guid, 4, 5);
61+
Swap(guid, 6, 7);
62+
}
63+
64+
private static void Swap(byte[] array, int index1, int index2)
65+
{
66+
var temp = array[index1];
67+
array[index1] = array[index2];
68+
array[index2] = temp;
69+
}
70+
public override object GetValue(IDataReader reader, int columnIndex, object[] values)
71+
{
72+
if (values != null)
73+
{
74+
if (values[columnIndex] == DBNull.Value)
75+
return null;
76+
}
77+
else
78+
{
79+
if (reader.IsDBNull(columnIndex))
80+
return null;
81+
}
82+
83+
return reader.GetGuid(columnIndex);
84+
}
85+
}
86+
3687
}

src/ServiceStack.OrmLite.Sqlite/SqliteOrmLiteDialectProviderBase.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
using System.Data;
44
using System.IO;
55
using System.Reflection;
6+
using System.Threading;
7+
using System.Threading.Tasks;
68
using ServiceStack.OrmLite.Sqlite.Converters;
79
using ServiceStack.Text;
810

@@ -17,7 +19,7 @@ protected SqliteOrmLiteDialectProviderBase()
1719
base.InitColumnTypeMap();
1820

1921
OrmLiteConfig.DeoptimizeReader = true;
20-
base.RegisterConverter<DateTime>(new SqliteSystemDataDateTimeConverter());
22+
base.RegisterConverter<DateTime>(new SqliteCoreDateTimeConverter());
2123
//Old behavior using native sqlite3.dll
2224
//base.RegisterConverter<DateTime>(new SqliteNativeDateTimeConverter());
2325

@@ -245,6 +247,14 @@ public override string SqlConflict(string sql, string conflictResolution)
245247
public override string SqlBool(bool value) => value ? "1" : "0";
246248

247249
public override string SqlRandom => "random()";
250+
251+
public override void EnableForeignKeysCheck(IDbCommand cmd) => cmd.ExecNonQuery($"PRAGMA foreign_keys = ON;");
252+
public override Task EnableForeignKeysCheckAsync(IDbCommand cmd, CancellationToken token = default) =>
253+
cmd.ExecNonQueryAsync($"PRAGMA foreign_keys = ON;", null, token);
254+
255+
public override void DisableForeignKeysCheck(IDbCommand cmd) => cmd.ExecNonQuery($"PRAGMA foreign_keys = OFF;");
256+
public override Task DisableForeignKeysCheckAsync(IDbCommand cmd, CancellationToken token = default) =>
257+
cmd.ExecNonQueryAsync($"PRAGMA foreign_keys = OFF;", null, token);
248258
}
249259

250260
public static class SqliteExtensions

src/ServiceStack.OrmLite/OrmLiteWriteApi.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,11 +360,16 @@ public static bool Save<T>(this IDbConnection dbConn, T obj, bool references = f
360360
if (!references)
361361
return dbConn.Exec(dbCmd => dbCmd.Save(obj));
362362

363+
var trans = dbConn.OpenTransactionIfNotExists();
363364
return dbConn.Exec(dbCmd =>
364365
{
365-
var ret = dbCmd.Save(obj);
366-
dbCmd.SaveAllReferences(obj);
367-
return ret;
366+
using (trans)
367+
{
368+
var ret = dbCmd.Save(obj);
369+
dbCmd.SaveAllReferences(obj);
370+
trans?.Commit();
371+
return ret;
372+
}
368373
});
369374
}
370375

src/ServiceStack.OrmLite/OrmLiteWriteApiAsync.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,11 +348,16 @@ public static async Task<bool> SaveAsync<T>(this IDbConnection dbConn, T obj, bo
348348
if (!references)
349349
return await dbConn.Exec(dbCmd => dbCmd.SaveAsync(obj, token)).ConfigAwait();
350350

351+
var trans = dbConn.OpenTransactionIfNotExists();
351352
return await dbConn.Exec(async dbCmd =>
352353
{
353-
var ret = await dbCmd.SaveAsync(obj, token).ConfigAwait();
354-
await dbCmd.SaveAllReferencesAsync(obj, token).ConfigAwait();
355-
return ret;
354+
using (trans)
355+
{
356+
var ret = await dbCmd.SaveAsync(obj, token).ConfigAwait();
357+
await dbCmd.SaveAllReferencesAsync(obj, token).ConfigAwait();
358+
trans?.Commit();
359+
return ret;
360+
}
356361
}).ConfigAwait();
357362
}
358363

tests/ServiceStack.OrmLite.Tests/DefaultValueTests.cs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -385,17 +385,16 @@ public void Can_use_ToUpdateStatement_to_generate_inline_SQL()
385385
[Test]
386386
public void Can_filter_update_method1_to_insert_date()
387387
{
388-
using (var db = OpenDbConnection())
389-
{
390-
CreateAndInitialize(db, 2);
388+
using var db = OpenDbConnection();
389+
CreateAndInitialize(db, 2);
391390

392-
ResetUpdateDate(db);
393-
db.Update(cmd => cmd.SetUpdateDate<MySqlDefaultValues>(nameof(MySqlDefaultValues.UpdatedDateUtc), DialectProvider),
394-
new MySqlDefaultValues { Id = 1, DefaultInt = 45 },
395-
new MySqlDefaultValues { Id = 2, DefaultInt = 72 });
396-
VerifyUpdateDate(db);
397-
VerifyUpdateDate(db, id: 2);
398-
}
391+
ResetUpdateDate(db);
392+
db.Update(cmd =>
393+
cmd.SetUpdateDate<MySqlDefaultValues>(nameof(MySqlDefaultValues.UpdatedDateUtc), DialectProvider),
394+
new MySqlDefaultValues { Id = 1, DefaultInt = 45 },
395+
new MySqlDefaultValues { Id = 2, DefaultInt = 72 });
396+
VerifyUpdateDate(db);
397+
VerifyUpdateDate(db, id: 2);
399398
}
400399

401400
private static void ResetUpdateDate(IDbConnection db)

tests/ServiceStack.OrmLite.Tests/Issues/LoadReferenceIssueWithCyclicalForeignKeys.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Generic;
2+
using System.Data;
23
using System.Threading.Tasks;
34
using NUnit.Framework;
45
using ServiceStack.DataAnnotations;
@@ -40,12 +41,19 @@ public class NameEntity : BaseEntity
4041
public ResearchEntity Research { get; set; }
4142
}
4243

44+
private void RecreateTables(IDbConnection db)
45+
{
46+
db.DisableForeignKeysCheck();
47+
db.DropAndCreateTable<NameEntity>();
48+
db.DropAndCreateTable<ResearchEntity>();
49+
db.EnableForeignKeysCheck();
50+
}
51+
4352
[Test]
4453
public void Does_update_self_FK_Key_when_saving_references()
4554
{
4655
using var db = OpenDbConnection();
47-
db.DropAndCreateTable<NameEntity>();
48-
db.DropAndCreateTable<ResearchEntity>();
56+
RecreateTables(db);
4957

5058
for (var i = 1; i <= 5; i++)
5159
{
@@ -70,8 +78,7 @@ public void Does_update_self_FK_Key_when_saving_references()
7078
public async Task Does_update_self_FK_Key_when_saving_references_Async()
7179
{
7280
using var db = await OpenDbConnectionAsync();
73-
db.DropAndCreateTable<NameEntity>();
74-
db.DropAndCreateTable<ResearchEntity>();
81+
RecreateTables(db);
7582

7683
for (var i = 1; i <= 5; i++)
7784
{

tests/ServiceStack.OrmLite.Tests/Issues/LoadReferencesForeignKeyTests.cs

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Data;
34
using System.Threading.Tasks;
45
using NUnit.Framework;
56
using ServiceStack.DataAnnotations;
@@ -101,20 +102,51 @@ public class UserAddress
101102
public string Details { get; set; }
102103
}
103104

105+
private static void InitDb(IDbConnection db)
106+
{
107+
db.DropTable<UserMeta>();
108+
db.DropTable<UserAddress>();
109+
db.DropTable<UserBranch>();
110+
db.DropTable<User>();
111+
112+
db.CreateTable<User>();
113+
db.CreateTable<UserBranch>();
114+
db.CreateTable<UserAddress>();
115+
db.CreateTable<UserMeta>();
116+
}
117+
118+
[Test]
119+
public void Can_create_tables_with_multiple_references()
120+
{
121+
using (var db = OpenDbConnection())
122+
{
123+
InitDb(db);
124+
}
125+
126+
var userMeta = new UserMeta();
127+
var user = new User
128+
{
129+
Meta = userMeta
130+
};
131+
132+
using (var db = OpenDbConnection())
133+
{
134+
user.Branches = new List<UserBranch> { new() { UserId = user.Id }};
135+
user.Addresses = new List<UserAddress> { new() { UserId = user.Id }};
136+
137+
db.Save(user, references: true);
138+
139+
var fromDb = db.LoadSingleById<User>(user.Id);
140+
fromDb.Dump().Print();
141+
}
142+
}
143+
104144
[Test]
105-
public async Task Can_create_tables_with_multiple_references()
145+
public async Task Can_create_tables_with_multiple_references_async()
106146
{
107147
using (var db = await OpenDbConnectionAsync())
108148
{
109-
db.DropTable<UserMeta>();
110-
db.DropTable<UserAddress>();
111-
db.DropTable<UserBranch>();
112-
db.DropTable<User>();
113-
114-
db.CreateTable<User>();
115-
db.CreateTable<UserBranch>();
116-
db.CreateTable<UserAddress>();
117-
db.CreateTable<UserMeta>();
149+
InitDb(db);
118150
}
119151

120152
var userMeta = new UserMeta();
@@ -125,8 +157,8 @@ public async Task Can_create_tables_with_multiple_references()
125157

126158
using (var db = await OpenDbConnectionAsync())
127159
{
128-
user.Branches = new List<UserBranch> { new UserBranch { UserId = user.Id }};
129-
user.Addresses = new List<UserAddress> { new UserAddress { UserId = user.Id }};
160+
user.Branches = new List<UserBranch> { new() { UserId = user.Id }};
161+
user.Addresses = new List<UserAddress> { new() { UserId = user.Id }};
130162

131163
await db.SaveAsync(user, references: true);
132164

tests/ServiceStack.OrmLite.Tests/SchemaTests.cs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -145,29 +145,27 @@ public void Can_drop_and_add_column()
145145
[Test]
146146
public void Can_get_Schema_Table()
147147
{
148-
using (var db = OpenDbConnection())
149-
{
150-
db.CreateTableIfNotExists<Person>();
148+
using var db = OpenDbConnection();
149+
db.CreateTableIfNotExists<Person>();
151150

152-
var columnSchemas = db.GetTableColumns<Person>();
151+
var columnSchemas = db.GetTableColumns<Person>();
153152

154-
columnSchemas.Each(x => x.ToString().Print());
153+
columnSchemas.Each(x => x.ToString().Print());
155154

156-
columnSchemas.Each(x => x.PrintDump());
157-
}
155+
// columnSchemas.Each(x => x.PrintDump());
156+
columnSchemas.Each(x => x.ToString().Print());
158157
}
159158

160159
[Test]
161160
public async Task Can_get_Schema_Table_Async()
162161
{
163-
using (var db = OpenDbConnection())
164-
{
165-
db.CreateTableIfNotExists<Person>();
162+
using var db = await OpenDbConnectionAsync();
163+
db.CreateTableIfNotExists<Person>();
166164

167-
var columnSchemas = await db.GetTableColumnsAsync<Person>();
165+
var columnSchemas = await db.GetTableColumnsAsync<Person>();
168166

169-
columnSchemas.Each(x => x.PrintDump());
170-
}
167+
// columnSchemas.Each(x => x.PrintDump());
168+
columnSchemas.Each(x => x.ToString().Print());
171169
}
172170

173171
[Test]

0 commit comments

Comments
 (0)