diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 173531df..ba2aa93c 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -46,8 +46,8 @@ jobs:
run: dotnet test tests/Dapper.Tests.Contrib/Dapper.Tests.Contrib.csproj -c Release --logger GitHubActions /p:CI=true
env:
MySqlConnectionString: Server=localhost;Port=${{ job.services.mysql.ports[3306] }};Uid=root;Pwd=root;Database=test;Allow User Variables=true
- OLEDBConnectionString: Provider=SQLOLEDB;Server=tcp:localhost,${{ job.services.sqlserver.ports[1433] }};Database=tempdb;User Id=sa;Password=Password.;
+ OLEDBConnectionString: Provider=SQLOLEDB;Server=tcp:localhost,${{ job.services.sqlserver.ports[1433] }};Database=tempdb;User Id=sa;Password=Password.;TrustServerCertificate=True;
PostgesConnectionString: Server=localhost;Port=${{ job.services.postgres.ports[5432] }};Database=test;User Id=postgres;Password=postgres;
- SqlServerConnectionString: Server=tcp:localhost,${{ job.services.sqlserver.ports[1433] }};Database=tempdb;User Id=sa;Password=Password.;
+ SqlServerConnectionString: Server=tcp:localhost,${{ job.services.sqlserver.ports[1433] }};Database=tempdb;User Id=sa;Password=Password.;TrustServerCertificate=True;
- name: .NET Lib Pack
run: dotnet pack Build.csproj --no-build -c Release /p:PackageOutputPath=%CD%\.nupkgs /p:CI=true
diff --git a/Dapper.sln b/Dapper.sln
index e993c7a4..19eed964 100644
--- a/Dapper.sln
+++ b/Dapper.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.28917.182
+# Visual Studio Version 17
+VisualStudioVersion = 17.11.35312.102
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A34907DF-958A-4E4C-8491-84CF303FD13E}"
ProjectSection(SolutionItems) = preProject
@@ -11,12 +11,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
Directory.Build.props = Directory.Build.props
docs\index.md = docs\index.md
License.txt = License.txt
+ .github\workflows\main.yml = .github\workflows\main.yml
nuget.config = nuget.config
Readme.md = Readme.md
version.json = version.json
EndProjectSection
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Contrib", "Dapper.Contrib\Dapper.Contrib.csproj", "{4E409F8F-CFBB-4332-8B0A-FD5A283051FD}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Contrib", "src\Dapper.Contrib\Dapper.Contrib.csproj", "{4E409F8F-CFBB-4332-8B0A-FD5A283051FD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Tests.Contrib", "tests\Dapper.Tests.Contrib\Dapper.Tests.Contrib.csproj", "{DAB3C5B7-BCD1-4A5F-BB6B-50D2BB63DB4A}"
EndProject
diff --git a/Readme.md b/Readme.md
index 9a1fd892..9acdd59d 100644
--- a/Readme.md
+++ b/Readme.md
@@ -133,10 +133,10 @@ Special Attributes
----------
Dapper.Contrib makes use of some optional attributes:
-* `[Table("Tablename")]` - use another table name instead of the (by default pluralized) name of the class
+* `[Table("Tablename", Schema = "SchemaName")]` - use another table name instead of the (by default pluralized) name of the class, Schema can be optionally passed as well.
```csharp
- [Table ("emps")]
+ [Table ("emps", Schema = "emp")]
public class Employee
{
public int Id { get; set; }
diff --git a/appveyor.yml b/appveyor.yml
index d91b9d19..53a05626 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,4 @@
-image: Visual Studio 2019
+image: Visual Studio 2022
skip_branch_with_pr: true
skip_tags: true
@@ -9,14 +9,14 @@ skip_commits:
environment:
Appveyor: true
# Postgres
- POSTGRES_PATH: C:\Program Files\PostgreSQL\9.6
+ POSTGRES_PATH: C:\Program Files\PostgreSQL\13
PGUSER: postgres
PGPASSWORD: Password12!
POSTGRES_ENV_POSTGRES_USER: postgres
POSTGRES_ENV_POSTGRES_PASSWORD: Password12!
POSTGRES_ENV_POSTGRES_DB: test
# MySQL
- MYSQL_PATH: C:\Program Files\MySql\MySQL Server 5.7
+ MYSQL_PATH: C:\Program Files\MySQL\MySQL Server 8.0
MYSQL_PWD: Password12!
MYSQL_ENV_MYSQL_USER: root
MYSQL_ENV_MYSQL_PASSWORD: Password12!
@@ -25,16 +25,17 @@ environment:
MySqlConnectionString: Server=localhost;Database=test;Uid=root;Pwd=Password12!
OLEDBConnectionString: Provider=SQLOLEDB;Data Source=(local)\SQL2019;Initial Catalog=tempdb;User Id=sa;Password=Password12!
PostgesConnectionString: Server=localhost;Port=5432;User Id=postgres;Password=Password12!;Database=test
- SqlServerConnectionString: Server=(local)\SQL2019;Database=tempdb;User ID=sa;Password=Password12!
+ SqlServerConnectionString: Server=(local)\SQL2019;Database=tempdb;User ID=sa;Password=Password12!;TrustServerCertificate=True
-services:
- - mysql
- - postgresql
+services:
+ - postgresql13
init:
+ - ps: Start-Service MySQL80
- git config --global core.autocrlf input
- SET PATH=%POSTGRES_PATH%\bin;%MYSQL_PATH%\bin;%PATH%
- net start MSSQL$SQL2019
+
nuget:
disable_publish_on_pr: true
diff --git a/src/Dapper.Contrib/Dapper.Contrib.csproj b/src/Dapper.Contrib/Dapper.Contrib.csproj
index 86a0cbb2..1ec842c9 100644
--- a/src/Dapper.Contrib/Dapper.Contrib.csproj
+++ b/src/Dapper.Contrib/Dapper.Contrib.csproj
@@ -5,12 +5,12 @@
orm;sql;micro-orm;dapper
The official collection of get, insert, update and delete helpers for Dapper.net. Also handles lists of entities and optional "dirty" tracking of interface-based entities.
Sam Saffron;Johan Danforth
- net461;netstandard2.0;net5.0
+ net6.0;net7.0;net8.0
false
$(NoWarn);CA1050
-
+
@@ -19,4 +19,12 @@
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
+
+
\ No newline at end of file
diff --git a/src/Dapper.Contrib/SqlMapperExtensions.cs b/src/Dapper.Contrib/SqlMapperExtensions.cs
index 9a30e805..a6be48d4 100644
--- a/src/Dapper.Contrib/SqlMapperExtensions.cs
+++ b/src/Dapper.Contrib/SqlMapperExtensions.cs
@@ -1,17 +1,16 @@
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
-using System.Text;
-using System.Collections.Concurrent;
using System.Reflection.Emit;
-using System.Threading;
-
+using System.Text;
using Dapper;
namespace Dapper.Contrib.Extensions
{
+
///
/// The Dapper.Contrib extensions for Dapper
///
@@ -187,7 +186,7 @@ public static T Get(this IDbConnection connection, dynamic id, IDbTransaction
if (type.IsInterface)
{
- if (!(connection.Query(sql, dynParams).FirstOrDefault() is IDictionary res))
+ if (connection.Query(sql, dynParams).FirstOrDefault() is not IDictionary res)
{
return null;
}
@@ -292,6 +291,13 @@ private static string GetTableName(Type type)
type.GetCustomAttribute(false)?.Name
?? (type.GetCustomAttributes(false).FirstOrDefault(attr => attr.GetType().Name == "TableAttribute") as dynamic)?.Name;
+ var tableAttrSchema = type.GetCustomAttribute(false)?.Schema;
+
+ if (!string.IsNullOrEmpty(tableAttrSchema))
+ {
+ tableAttrName = $"{tableAttrSchema}.{tableAttrName}";
+ }
+
if (tableAttrName != null)
{
name = tableAttrName;
@@ -299,7 +305,7 @@ private static string GetTableName(Type type)
else
{
name = type.Name + "s";
- if (type.IsInterface && name.StartsWith("I"))
+ if (type.IsInterface && name.StartsWith('I'))
name = name.Substring(1);
}
}
@@ -601,7 +607,7 @@ public static T GetInterfaceProxy()
return (T)Activator.CreateInstance(generatedType);
}
- private static MethodInfo CreateIsDirtyProperty(TypeBuilder typeBuilder)
+ private static MethodBuilder CreateIsDirtyProperty(TypeBuilder typeBuilder)
{
var propType = typeof(bool);
var field = typeBuilder.DefineField("_" + nameof(IProxy.IsDirty), propType, FieldAttributes.Private);
@@ -642,7 +648,7 @@ private static MethodInfo CreateIsDirtyProperty(TypeBuilder typeBuilder)
return currSetPropMthdBldr;
}
- private static void CreateProperty(TypeBuilder typeBuilder, string propertyName, Type propType, MethodInfo setIsDirtyMethod, bool isIdentity)
+ private static void CreateProperty(TypeBuilder typeBuilder, string propertyName, Type propType, MethodBuilder setIsDirtyMethod, bool isIdentity)
{
//Define the field and the property
var field = typeBuilder.DefineField("_" + propertyName, propType, FieldAttributes.Private);
@@ -710,15 +716,22 @@ public class TableAttribute : Attribute
/// Creates a table mapping to a specific name for Dapper.Contrib commands
///
/// The name of this table in the database.
- public TableAttribute(string tableName)
+ /// The schema name of this table in the database
+ public TableAttribute(string tableName, string schema = "")
{
Name = tableName;
+ Schema = schema;
}
///
/// The name of the table in the database
///
public string Name { get; set; }
+
+ ///
+ /// The schema of the table in the database
+ ///
+ public string Schema { get; set; }
}
///
diff --git a/tests/Dapper.Tests.Contrib/Dapper.Tests.Contrib.csproj b/tests/Dapper.Tests.Contrib/Dapper.Tests.Contrib.csproj
index d217f0ce..3d317311 100644
--- a/tests/Dapper.Tests.Contrib/Dapper.Tests.Contrib.csproj
+++ b/tests/Dapper.Tests.Contrib/Dapper.Tests.Contrib.csproj
@@ -2,7 +2,7 @@
Dapper.Tests.Contrib
Dapper Contrib Test Suite
- netcoreapp3.1;net462;net5.0
+ net6.0;net7.0;net8.0
$(NoWarn);CA1816;IDE0063;xUnit1004
@@ -13,11 +13,29 @@
-
-
-
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
diff --git a/tests/Dapper.Tests.Contrib/TestSuite.Async.cs b/tests/Dapper.Tests.Contrib/TestSuite.Async.cs
index fcd11802..849537c5 100644
--- a/tests/Dapper.Tests.Contrib/TestSuite.Async.cs
+++ b/tests/Dapper.Tests.Contrib/TestSuite.Async.cs
@@ -4,7 +4,6 @@
using System.Threading.Tasks;
using Dapper.Contrib.Extensions;
-using FactAttribute = Dapper.Tests.Contrib.SkippableFactAttribute;
using Xunit;
namespace Dapper.Tests.Contrib
@@ -125,7 +124,7 @@ public async Task InsertGetUpdateDeleteWithExplicitKeyAsync()
var list2 = (await connection.QueryAsync("select * from ObjectY").ConfigureAwait(false)).ToList();
Assert.Equal(list2.Count, originalyCount + 1);
o2 = await connection.GetAsync(id).ConfigureAwait(false);
- Assert.Equal(o2.ObjectYId, id);
+ Assert.Equal(id, o2.ObjectYId);
o2.Name = "Bar";
await connection.UpdateAsync(o2).ConfigureAwait(false);
o2 = await connection.GetAsync(id).ConfigureAwait(false);
@@ -305,9 +304,9 @@ private async Task InsertHelperAsync(Func, T> helper)
await connection.DeleteAllAsync().ConfigureAwait(false);
var total = await connection.InsertAsync(helper(users)).ConfigureAwait(false);
- Assert.Equal(total, numberOfEntities);
+ Assert.Equal(numberOfEntities, total);
users = connection.Query("select * from Users").ToList();
- Assert.Equal(users.Count, numberOfEntities);
+ Assert.Equal(numberOfEntities, users.Count);
}
}
@@ -343,9 +342,9 @@ private async Task UpdateHelperAsync(Func, T> helper)
await connection.DeleteAllAsync().ConfigureAwait(false);
var total = await connection.InsertAsync(helper(users)).ConfigureAwait(false);
- Assert.Equal(total, numberOfEntities);
+ Assert.Equal(numberOfEntities, total);
users = connection.Query("select * from Users").ToList();
- Assert.Equal(users.Count, numberOfEntities);
+ Assert.Equal(numberOfEntities, users.Count);
foreach (var user in users)
{
user.Name += " updated";
@@ -377,7 +376,7 @@ public async Task DeleteListAsync()
private async Task DeleteHelperAsync(Func, T> helper)
where T : class
{
- const int numberOfEntities = 10;
+ int numberOfEntities = 10;
var users = new List(numberOfEntities);
for (var i = 0; i < numberOfEntities; i++)
@@ -388,14 +387,14 @@ private async Task DeleteHelperAsync(Func, T> helper)
await connection.DeleteAllAsync().ConfigureAwait(false);
var total = await connection.InsertAsync(helper(users)).ConfigureAwait(false);
- Assert.Equal(total, numberOfEntities);
+ Assert.Equal(numberOfEntities, total);
users = connection.Query("select * from Users").ToList();
- Assert.Equal(users.Count, numberOfEntities);
+ Assert.Equal(numberOfEntities, users.Count);
var usersToDelete = users.Take(10).ToList();
await connection.DeleteAsync(helper(usersToDelete)).ConfigureAwait(false);
users = connection.Query("select * from Users").ToList();
- Assert.Equal(users.Count, numberOfEntities - 10);
+ Assert.Equal(numberOfEntities - 10, users.Count);
}
}
@@ -413,11 +412,11 @@ public async Task GetAllAsync()
await connection.DeleteAllAsync().ConfigureAwait(false);
var total = await connection.InsertAsync(users).ConfigureAwait(false);
- Assert.Equal(total, numberOfEntities);
+ Assert.Equal(numberOfEntities, total);
users = (List)await connection.GetAllAsync().ConfigureAwait(false);
- Assert.Equal(users.Count, numberOfEntities);
+ Assert.Equal(numberOfEntities, users.Count);
var iusers = await connection.GetAllAsync().ConfigureAwait(false);
- Assert.Equal(iusers.ToList().Count, numberOfEntities);
+ Assert.Equal(numberOfEntities, iusers.ToList().Count);
}
}
@@ -436,12 +435,12 @@ public async void GetAsyncAndGetAllAsyncWithNullableValues()
Assert.Equal(new DateTime(2011, 07, 14), value1.DateValue.Value);
var value2 = await connection.GetAsync(id2).ConfigureAwait(false);
- Assert.True(value2.DateValue == null);
+ Assert.Null(value2.DateValue);
var value3 = await connection.GetAllAsync().ConfigureAwait(false);
var valuesList = value3.ToList();
Assert.Equal(new DateTime(2011, 07, 14), valuesList[0].DateValue.Value);
- Assert.True(valuesList[1].DateValue == null);
+ Assert.Null(valuesList[1].DateValue);
}
}
diff --git a/tests/Dapper.Tests.Contrib/TestSuite.cs b/tests/Dapper.Tests.Contrib/TestSuite.cs
index 71dbd8ad..8f690de9 100644
--- a/tests/Dapper.Tests.Contrib/TestSuite.cs
+++ b/tests/Dapper.Tests.Contrib/TestSuite.cs
@@ -5,8 +5,6 @@
using Dapper.Contrib.Extensions;
using Xunit;
-using FactAttribute = Dapper.Tests.Contrib.SkippableFactAttribute;
-
namespace Dapper.Tests.Contrib
{
[Table("ObjectX")]
@@ -247,7 +245,7 @@ public void InsertGetUpdateDeleteWithExplicitKey()
var list2 = connection.Query("select * from ObjectY").ToList();
Assert.Equal(list2.Count, originalyCount + 1);
o2 = connection.Get(id);
- Assert.Equal(o2.ObjectYId, id);
+ Assert.Equal(id, o2.ObjectYId);
o2.Name = "Bar";
connection.Update(o2);
o2 = connection.Get(id);
@@ -284,7 +282,7 @@ public void InsertGetUpdateDeleteWithExplicitKeyNamedId()
var list2 = connection.Query("select * from ObjectZ").ToList();
Assert.Single(list2);
o2 = connection.Get(id);
- Assert.Equal(o2.Id, id);
+ Assert.Equal(id, o2.Id);
}
}
@@ -298,7 +296,7 @@ public void ShortIdentity()
Assert.True(id > 0); // 1-n are valid here, due to parallel tests
var item = connection.Get(id);
Assert.Equal(item.TheId, (short)id);
- Assert.Equal(item.Name, name);
+ Assert.Equal(name, item.Name);
}
}
@@ -389,9 +387,9 @@ private void InsertHelper(Func, T> helper)
connection.DeleteAll();
var total = connection.Insert(helper(users));
- Assert.Equal(total, numberOfEntities);
+ Assert.Equal(numberOfEntities, total);
users = connection.Query("select * from Users").ToList();
- Assert.Equal(users.Count, numberOfEntities);
+ Assert.Equal(numberOfEntities, users.Count);
}
}
@@ -427,9 +425,9 @@ private void UpdateHelper(Func, T> helper)
connection.DeleteAll();
var total = connection.Insert(helper(users));
- Assert.Equal(total, numberOfEntities);
+ Assert.Equal(numberOfEntities, total);
users = connection.Query("select * from Users").ToList();
- Assert.Equal(users.Count, numberOfEntities);
+ Assert.Equal(numberOfEntities, users.Count);
foreach (var user in users)
{
user.Name += " updated";
@@ -461,7 +459,7 @@ public void DeleteList()
private void DeleteHelper(Func, T> helper)
where T : class
{
- const int numberOfEntities = 10;
+ int numberOfEntities = 10;
var users = new List(numberOfEntities);
for (var i = 0; i < numberOfEntities; i++)
@@ -472,14 +470,14 @@ private void DeleteHelper(Func, T> helper)
connection.DeleteAll();
var total = connection.Insert(helper(users));
- Assert.Equal(total, numberOfEntities);
+ Assert.Equal(numberOfEntities, total);
users = connection.Query("select * from Users").ToList();
- Assert.Equal(users.Count, numberOfEntities);
+ Assert.Equal(numberOfEntities, users.Count);
var usersToDelete = users.Take(10).ToList();
connection.Delete(helper(usersToDelete));
users = connection.Query("select * from Users").ToList();
- Assert.Equal(users.Count, numberOfEntities - 10);
+ Assert.Equal(numberOfEntities - 10, users.Count);
}
}
@@ -569,7 +567,7 @@ public void InsertWithCustomTableNameMapper()
return tableattr.Name;
var name = type.Name + "s";
- if (type.IsInterface && name.StartsWith("I"))
+ if (type.IsInterface && name.StartsWith('I'))
return name.Substring(1);
return name;
}
@@ -597,13 +595,13 @@ public void GetAll()
connection.DeleteAll();
var total = connection.Insert(users);
- Assert.Equal(total, numberOfEntities);
+ Assert.Equal(numberOfEntities, total);
users = connection.GetAll().ToList();
- Assert.Equal(users.Count, numberOfEntities);
+ Assert.Equal(numberOfEntities, users.Count);
var iusers = connection.GetAll().ToList();
- Assert.Equal(iusers.Count, numberOfEntities);
+ Assert.Equal(numberOfEntities, iusers.Count);
for (var i = 0; i < numberOfEntities; i++)
- Assert.Equal(iusers[i].Age, i);
+ Assert.Equal(i, iusers[i].Age);
}
}
@@ -622,11 +620,11 @@ public void GetAndGetAllWithNullableValues()
Assert.Equal(new DateTime(2011, 07, 14), value1.DateValue.Value);
var value2 = connection.Get(id2);
- Assert.True(value2.DateValue == null);
+ Assert.Null(value2.DateValue);
var value3 = connection.GetAll().ToList();
Assert.Equal(new DateTime(2011, 07, 14), value3[0].DateValue.Value);
- Assert.True(value3[1].DateValue == null);
+ Assert.Null(value3[1].DateValue);
}
}
diff --git a/tests/Dapper.Tests.Contrib/TestSuites.cs b/tests/Dapper.Tests.Contrib/TestSuites.cs
index 55d4ef5c..5a23d629 100644
--- a/tests/Dapper.Tests.Contrib/TestSuites.cs
+++ b/tests/Dapper.Tests.Contrib/TestSuites.cs
@@ -1,8 +1,8 @@
-using Microsoft.Data.Sqlite;
+using Microsoft.Data.SqlClient;
+using Microsoft.Data.Sqlite;
using MySqlConnector;
using System;
using System.Data;
-using System.Data.SqlClient;
using System.IO;
using Xunit;
using Xunit.Sdk;