diff --git a/.gitignore b/.gitignore index 4aaead6..e768b33 100644 --- a/.gitignore +++ b/.gitignore @@ -294,4 +294,5 @@ __pycache__/ *.odx.cs *.xsd.cs -*license.txt \ No newline at end of file +*license.txt +/src/UnitTests/Resources/test_tmp.db diff --git a/src/Dapper.Contrib.Linq2Dapper.sln b/src/Dapper.Contrib.Linq2Dapper.sln index 1985fa2..aa94496 100644 --- a/src/Dapper.Contrib.Linq2Dapper.sln +++ b/src/Dapper.Contrib.Linq2Dapper.sln @@ -1,9 +1,11 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26430.16 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30523.141 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper.Contrib.Linq2Dapper", "Linq2Dapper\Dapper.Contrib.Linq2Dapper.csproj", "{6790F728-CB22-44BE-972E-7287373720D4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Contrib.Linq2Dapper", "Linq2Dapper\Dapper.Contrib.Linq2Dapper.csproj", "{6790F728-CB22-44BE-972E-7287373720D4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests", "UnitTests\UnitTests.csproj", "{FF3463B1-BCD0-45A1-8AE4-523A276521A6}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -15,8 +17,15 @@ Global {6790F728-CB22-44BE-972E-7287373720D4}.Debug|Any CPU.Build.0 = Debug|Any CPU {6790F728-CB22-44BE-972E-7287373720D4}.Release|Any CPU.ActiveCfg = Release|Any CPU {6790F728-CB22-44BE-972E-7287373720D4}.Release|Any CPU.Build.0 = Release|Any CPU + {FF3463B1-BCD0-45A1-8AE4-523A276521A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FF3463B1-BCD0-45A1-8AE4-523A276521A6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FF3463B1-BCD0-45A1-8AE4-523A276521A6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FF3463B1-BCD0-45A1-8AE4-523A276521A6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {185D6FA1-D6B8-438C-ABF9-AAC47EDA1585} + EndGlobalSection EndGlobal diff --git a/src/Linq2Dapper/Dapper.Contrib.Linq2Dapper.csproj b/src/Linq2Dapper/Dapper.Contrib.Linq2Dapper.csproj index 73b21da..093784d 100644 --- a/src/Linq2Dapper/Dapper.Contrib.Linq2Dapper.csproj +++ b/src/Linq2Dapper/Dapper.Contrib.Linq2Dapper.csproj @@ -1,76 +1,21 @@ - - - + + - Debug - AnyCPU - {6790F728-CB22-44BE-972E-7287373720D4} - Library - Properties - Dapper.Contrib.Linq2Dapper - Dapper.Contrib.Linq2Dapper - v4.5 - 512 - + netstandard2.0 + A simple light weight LINQ provider for Dapper.Net + https://github.com/brentmannering/linq-to-dapper/ + linq, dapper + Brent Mannering + 1.0.4 + Linq2Dapper - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - ..\packages\Dapper.1.42\lib\net45\Dapper.dll - True - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + - - - \ No newline at end of file + + + + diff --git a/src/Linq2Dapper/Extensions/DapperExtensions.cs b/src/Linq2Dapper/Extensions/DapperExtensions.cs index b88c86b..16cab68 100644 --- a/src/Linq2Dapper/Extensions/DapperExtensions.cs +++ b/src/Linq2Dapper/Extensions/DapperExtensions.cs @@ -17,5 +17,7 @@ public static async Task> QueryAsync(this IDbConnection dbConne { return await Task.Run(() => new Linq2Dapper(dbConnection, expression: expression)); } + + } } diff --git a/src/Linq2Dapper/Extensions/LinqExtensions.cs b/src/Linq2Dapper/Extensions/LinqExtensions.cs index b6829a9..2ab733d 100644 --- a/src/Linq2Dapper/Extensions/LinqExtensions.cs +++ b/src/Linq2Dapper/Extensions/LinqExtensions.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text; using System.Linq.Expressions; +using System.Linq; namespace Dapper.Contrib.Linq.Extensions { diff --git a/src/Linq2Dapper/Extensions/PropertyInfoExtensions.cs b/src/Linq2Dapper/Extensions/PropertyInfoExtensions.cs new file mode 100644 index 0000000..e8e8b39 --- /dev/null +++ b/src/Linq2Dapper/Extensions/PropertyInfoExtensions.cs @@ -0,0 +1,15 @@ +using System.Collections; +using System.Linq; +using System.Reflection; + +namespace Dapper.Contrib.Linq2Dapper.Extensions +{ + public static class PropertyInfoExtensions + { + public static bool IsStatic(this PropertyInfo source, bool nonPublic = false) + => source.GetAccessors(nonPublic).Any(x => x.IsStatic); + + public static bool IsList(this PropertyInfo source, bool nonPublic = false) + => typeof(IEnumerable).IsAssignableFrom(source.PropertyType); + } +} \ No newline at end of file diff --git a/src/Linq2Dapper/Helpers/QueryHelper.cs b/src/Linq2Dapper/Helpers/QueryHelper.cs index e7257c2..c1025b1 100644 --- a/src/Linq2Dapper/Helpers/QueryHelper.cs +++ b/src/Linq2Dapper/Helpers/QueryHelper.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using Dapper.Contrib.Linq2Dapper.Extensions; namespace Dapper.Contrib.Linq2Dapper.Helpers { @@ -257,7 +258,7 @@ internal static TableHelper GetTypeProperties(Type type) // get properties add to cache var properties = new Dictionary(); - type.GetProperties().ToList().ForEach( + type.GetProperties().Where(p => !p.IsStatic() && !p.IsList()).ToList().ForEach( x => { var col = (ColumnAttribute)x.GetCustomAttribute(typeof(ColumnAttribute)); diff --git a/src/Linq2Dapper/Linq2Dapper.cs b/src/Linq2Dapper/Linq2Dapper.cs index d1258ae..1b8b2f7 100644 --- a/src/Linq2Dapper/Linq2Dapper.cs +++ b/src/Linq2Dapper/Linq2Dapper.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Configuration; using System.Data; -using System.Data.SqlClient; using System.Linq; using System.Linq.Expressions; @@ -55,6 +53,17 @@ public Linq2Dapper(IDbConnection connection, IQueryProvider provider = null, Exp #region Properties + public string Sql + { + get + { + var provider = (QueryProvider)Provider; + provider.QueryBuilder.Evaluate(Expression); + return provider.QueryBuilder.Sql; + } + } + + public IQueryProvider Provider { get; private set; } public IDbConnection Connection { get; private set; } public Expression Expression { get; private set; } diff --git a/src/Linq2Dapper/Properties/AssemblyInfo.cs b/src/Linq2Dapper/Properties/AssemblyInfo.cs deleted file mode 100644 index 8e8226a..0000000 --- a/src/Linq2Dapper/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("DapperLinqProvider")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("DapperLinqProvider")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("f794ee69-93bd-47d9-b111-38940bfef27a")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Linq2Dapper/QueryProvider.cs b/src/Linq2Dapper/QueryProvider.cs index cbbe223..4fd3fde 100644 --- a/src/Linq2Dapper/QueryProvider.cs +++ b/src/Linq2Dapper/QueryProvider.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Data; -using System.Data.SqlClient; using System.Linq; using System.Linq.Expressions; using Dapper.Contrib.Linq2Dapper.Exceptions; @@ -13,12 +11,12 @@ namespace Dapper.Contrib.Linq2Dapper internal class QueryProvider : IQueryProvider { private readonly IDbConnection _connection; - private readonly QueryBuilder _qb; + internal readonly QueryBuilder QueryBuilder; public QueryProvider(IDbConnection connection) { _connection = connection; - _qb = new QueryBuilder(); + QueryBuilder = new QueryBuilder(); } public IQueryable CreateQuery(Expression expression) @@ -58,15 +56,15 @@ private object Query(Expression expression, bool isEnumerable = false) { if (_connection.State != ConnectionState.Open) _connection.Open(); - _qb.Evaluate(expression); - var data = _connection.Query(_qb.Sql, _qb.Parameters); + QueryBuilder.Evaluate(expression); + var data = _connection.Query(QueryBuilder.Sql, QueryBuilder.Parameters); if (isEnumerable) return data; return data.ElementAt(0); } - catch (SqlException ex) + catch (InvalidOperationException ex) { - throw new InvalidQueryException(ex.Message + " | " + _qb.Sql); + throw new InvalidQueryException(ex.Message + " | " + QueryBuilder.Sql); } finally { diff --git a/src/UnitTests/Models/Machine.cs b/src/UnitTests/Models/Machine.cs new file mode 100644 index 0000000..3bc02b1 --- /dev/null +++ b/src/UnitTests/Models/Machine.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text; + +namespace UnitTests.Models +{ + [Table("Machine")] + public class Machine + { + public int Id { get; set; } + public string Name { get; set; } + public DateTime DeliveredOn { get; set; } + public bool IsCool { get; set; } + + public static string MyStaticField { get;set;} + public List JustAList { get; set; } + public bool[] JustAnArray { get; set; } + } +} diff --git a/src/UnitTests/Resources/test.db b/src/UnitTests/Resources/test.db new file mode 100644 index 0000000..0b9d808 Binary files /dev/null and b/src/UnitTests/Resources/test.db differ diff --git a/src/UnitTests/UnitTest1.cs b/src/UnitTests/UnitTest1.cs new file mode 100644 index 0000000..038a9e0 --- /dev/null +++ b/src/UnitTests/UnitTest1.cs @@ -0,0 +1,74 @@ +using System; +using System.Data; +using System.IO; +using System.Linq; +using Dapper; +using Dapper.Contrib.Linq2Dapper; +using Dapper.Contrib.Linq2Dapper.Extensions; +using Microsoft.Data.Sqlite; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using UnitTests.Models; + +namespace UnitTests +{ + [TestClass] + public class UnitTest1 + { + public UnitTest1() + { + SqlMapper.AddTypeHandler(DateTimeHandler.Default); + } + [TestMethod] + public void TestMethod1() + { + var dbFolder = Path.GetFullPath(@"..\..\..\Resources\"); + var dbFile = Path.Combine(dbFolder, "test.db"); + var tmpDbFile = Path.Combine(dbFolder, "test_tmp.db"); + + File.Copy(dbFile,tmpDbFile,true); + + var connectionString = $@"Filename={tmpDbFile}"; + var connection = new SqliteConnection(connectionString); + + connection.Execute( + "insert into Machine (Id,Name,DeliveredOn,IsCool) values (@Id,@Name,@DeliveredOn,@IsCool)", + new { Id = 0, Name = "A", DeliveredOn = new DateTime(2000, 1, 1).Ticks, IsCool = false }); + connection.Execute( + "insert into Machine (Id,Name,DeliveredOn,IsCool) values (@Id,@Name,@DeliveredOn,@IsCool)", + new { Id = 1, Name = "B", DeliveredOn = new DateTime(2000, 1, 2).Ticks, IsCool = false }); + connection.Execute( + "insert into Machine (Id,Name,DeliveredOn,IsCool) values (@Id,@Name,@DeliveredOn,@IsCool)", + new { Id = 2, Name = "C", DeliveredOn = new DateTime(2000, 1, 3).Ticks, IsCool = true }); + connection.Execute( + "insert into Machine (Id,Name,DeliveredOn,IsCool) values (@Id,@Name,@DeliveredOn,@IsCool)", + new { Id = 3, Name = "D", DeliveredOn = new DateTime(2000, 1, 4).Ticks, IsCool = false }); + + var query = connection.Query(x => x.Id == 2); + + var results = query.AsList(); + Assert.AreEqual(1,results.Count); + Assert.AreEqual(2, results.First().Id); + Assert.AreEqual(new DateTime(2000, 1, 3), results.First().DeliveredOn); + + + } + + public class DateTimeHandler : SqlMapper.TypeHandler + { + public static readonly DateTimeHandler Default = new DateTimeHandler(); + + public override void SetValue(IDbDataParameter parameter, DateTime value) + { + + parameter.Value = value.Ticks; + } + + public override DateTime Parse(object value) + { + var ticks = Convert.ToInt64(value); + //var ticks = (long)value; + return new DateTime(ticks); + } + } + } +} diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj new file mode 100644 index 0000000..e224090 --- /dev/null +++ b/src/UnitTests/UnitTests.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp3.1 + + false + + + + + + + + + + + + + + +