Skip to content

Commit 1ba9e5d

Browse files
authored
Merge pull request #25 from cajuncoding/feature/enhance_property_handling_with_ignor_and_conversions
Feature/enhance property handling with ignor and conversions
2 parents 0de8bfb + ec81996 commit 1ba9e5d

File tree

53 files changed

+1304
-364
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1304
-364
lines changed

DotNetFramework.SqlBulkHelpers/DotNetFramework.SqlBulkHelpers-Deprecated.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
<WarningLevel>4</WarningLevel>
3333
</PropertyGroup>
3434
<ItemGroup>
35-
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
36-
<HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
35+
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
36+
<HintPath>..\packages\Newtonsoft.Json.13.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
3737
</Reference>
3838
<Reference Include="System" />
3939
<Reference Include="System.Configuration" />

DotNetFramework.SqlBulkHelpers/SqlBulkHelpers/Database/SqlBulkHelpersDBSchemaModels.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
64

75
namespace SqlBulkHelpers
86
{
@@ -51,18 +49,20 @@ public override string ToString()
5149

5250
public class SqlBulkHelpersColumnDefinition
5351
{
54-
public SqlBulkHelpersColumnDefinition(String columnName, int ordinalPosition, String dataType, bool isIdentityColumn)
52+
public SqlBulkHelpersColumnDefinition(String columnName, int ordinalPosition, String dataType, bool isIdentityColumn, bool isComputedColumn)
5553
{
5654
this.ColumnName = columnName;
5755
this.OrdinalPosition = ordinalPosition;
5856
this.DataType = dataType;
5957
this.IsIdentityColumn = isIdentityColumn;
58+
this.IsComputedColumn = isComputedColumn;
6059
}
6160

6261
public String ColumnName { get; private set; }
6362
public int OrdinalPosition { get; private set; }
6463
public String DataType { get; private set; }
6564
public bool IsIdentityColumn { get; private set; }
65+
public bool IsComputedColumn { get; private set; }
6666

6767
public override string ToString()
6868
{
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
3-
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net461" />
3+
<package id="Newtonsoft.Json" version="13.0.4" targetFramework="net48" />
44
</packages>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using SqlBulkHelpers.Interfaces;
2+
using System;
3+
using System.Text.Json;
4+
5+
namespace SqlBulkHelpers
6+
{
7+
/// <summary>
8+
/// Dynamically convert any property that is annotated with this attribute to JSON String before storing in the Database.
9+
/// Provides and example and helpful utility using hte ISqlBulkHelperPropertyConverter<TProp, TConverted> interface!
10+
/// </summary>
11+
[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
12+
public class SqlBulkConvertToJsonAttribute : Attribute, ISqlBulkHelpersPropertyTransformer
13+
{
14+
object ISqlBulkHelpersPropertyTransformer.TransformPropValue(object propValue)
15+
=> JsonSerializer.Serialize(
16+
propValue,
17+
SqlBulkHelpersConfig.DefaultConfig.SqlBulkJsonConverterSerializerOptions ?? new JsonSerializerOptions()
18+
);
19+
}
20+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace SqlBulkHelpers
6+
{
7+
[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
8+
public class SqlBulkIgnoreAttribute : Attribute
9+
{
10+
}
11+
}

NetStandard.SqlBulkHelpers/Attributes/SqlBulkMatchQualifierAttribute.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,5 @@ namespace SqlBulkHelpers
55
[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
66
public class SqlBulkMatchQualifierAttribute : Attribute
77
{
8-
public SqlBulkMatchQualifierAttribute()
9-
{
10-
}
118
}
129
}

NetStandard.SqlBulkHelpers/CustomExtensions/ReflectionExtensions.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,25 @@ namespace SqlBulkHelpers.SqlBulkHelpers.CustomExtensions
88
{
99
internal static class ReflectionExtensions
1010
{
11-
public static IEnumerable<Attribute> FindAttributes(this Type type, params string[] attributeNames)
11+
public static IList<Attribute> FindAttributesByName(this Type type, params string[] attributeNames)
1212
{
1313
if (type == null)
1414
return null;
1515

1616
var attributes = type.GetCustomAttributes(true).OfType<Attribute>();
17-
return FindAttributes(attributes, attributeNames);
17+
return FindAttributesByName(attributes, attributeNames);
1818
}
1919

20-
public static IEnumerable<Attribute> FindAttributes(this PropertyInfo propInfo, params string[] attributeNames)
20+
public static IList<Attribute> FindAttributesByName(this PropertyInfo propInfo, params string[] attributeNames)
2121
{
2222
if (propInfo == null)
2323
return null;
2424

2525
var attributes = propInfo.GetCustomAttributes(true).OfType<Attribute>();
26-
return FindAttributes(attributes, attributeNames);
26+
return FindAttributesByName(attributes, attributeNames);
2727
}
2828

29-
public static IEnumerable<Attribute> FindAttributes(this IEnumerable<Attribute> attributes, params string[] attributeNamesToFind)
29+
public static IList<Attribute> FindAttributesByName(this IEnumerable<Attribute> attributes, params string[] attributeNamesToFind)
3030
{
3131

3232
if (attributeNamesToFind.IsNullOrEmpty())
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using Fasterflect;
2+
using SqlBulkHelpers.Interfaces;
3+
using SqlBulkHelpers.SqlBulkHelpers.CustomExtensions;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Reflection;
8+
using System.Text;
9+
10+
namespace SqlBulkHelpers.CustomExtensions
11+
{
12+
internal static class RepoDbDynamicCustomExtensions
13+
{
14+
public static ISqlBulkHelpersPropertyTransformer FindRepoDbPropertyHandler(this PropertyInfo propInfo)
15+
{
16+
if (propInfo == null)
17+
return null;
18+
19+
// 2) Detect RepoDb's [PropertyHandler(typeof(...))] by name (no RepoDb reference required)
20+
var repoDbAttr = propInfo
21+
.FindAttributesByName(RepoDbNames.PropertyHandlerAttributeName)
22+
.FirstOrDefault();
23+
24+
if (repoDbAttr == null)
25+
return null;
26+
27+
// 3) Extract the handler type from the attribute with last ditch effort fallback if name/property differs
28+
var repoDbHandlerType = repoDbAttr.GetPropertyValue(RepoDbNames.PropertyHandlerTypePropertyName) as Type
29+
?? repoDbAttr.GetType().Properties().FirstOrDefault(p => p.CanRead && p.PropertyType == TypeCache.Type)?.GetValue(repoDbAttr) as Type;
30+
31+
if (repoDbHandlerType == null)
32+
return null;
33+
34+
// 4) Locate the 'Set' method: TInput Set(TResult input, PropertyHandlerSetOptions options);
35+
var repoDbHandlerSetMethod = repoDbHandlerType
36+
.Methods()
37+
.FirstOrDefault(m =>
38+
m.Name.Equals(RepoDbNames.PropertyHandlerSetMethodName, StringComparison.OrdinalIgnoreCase)
39+
&& !m.IsGenericMethodDefinition
40+
&& m.Parameters() is IList<ParameterInfo> methodParams
41+
&& methodParams.Count == 2 //Must have exactly 2 params (per RepoDb Interface) and validate the Name of the second param below...
42+
&& methodParams[0].ParameterType.IsAssignableFrom(propInfo.PropertyType) //Input Type (to be converted) must match the current Property Type we are processing!
43+
&& methodParams[1].ParameterType is Type methodType
44+
//The Set method is used to write value to the DB!
45+
&& (methodType.FullName ?? methodType.Name).IndexOf(RepoDbNames.PropertyHandlerSetOptionsClassName, StringComparison.OrdinalIgnoreCase) >= 0
46+
);
47+
48+
if (repoDbHandlerSetMethod == null)
49+
return null;
50+
51+
try
52+
{
53+
// 5) Create an instance of the PropertyHandler class (as only the Type is reference in the Attribute)
54+
object propertyHandlerInstance = repoDbHandlerType.CreateInstance(); // Fasterflect; falls back to Activator if needed
55+
56+
// 6) Create high‑performance Fasterflect invoker (delegate)
57+
var repoDbPropHandlerGetMethodInvoker = repoDbHandlerSetMethod.DelegateForCallMethod(); // returns Fasterflect.MethodInvoker
58+
59+
// For safety, ensure the first arg (TInput) matches/accepts the property type
60+
//NOTE: We already know we have 2 parameters above!
61+
var parameters = repoDbHandlerSetMethod.Parameters();
62+
var optionsParamType = parameters[1].ParameterType;
63+
64+
// Options: null for class, default(T) for struct which is returned when we try to create an instance...
65+
object optionsArg = optionsParamType.IsValueType
66+
? optionsParamType.CreateInstance()
67+
: null;
68+
69+
// 8) Return a converter wrapper Interfaced Func<object, object> to encapsulate the call to the Invoker
70+
// of the Get mehod of the PropertyHandler
71+
return new SqlBulkLambdaPropertyConverter(valueObj =>
72+
{
73+
if (valueObj is null) return null;
74+
return repoDbPropHandlerGetMethodInvoker.Invoke(propertyHandlerInstance, valueObj, optionsArg);
75+
});
76+
}
77+
catch
78+
{
79+
return null; // could not construct; ignore optional feature
80+
}
81+
}
82+
}
83+
}

NetStandard.SqlBulkHelpers/CustomExtensions/SqlBulkHelpersCustomExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public static string MakeTableNameUnique(this string tableNameToMakeUnique, int
107107
if (string.IsNullOrWhiteSpace(tableNameToMakeUnique))
108108
throw new ArgumentNullException(nameof(tableNameToMakeUnique));
109109

110-
var uniqueTokenSuffix = string.Concat("_", IdGenerator.NewId(uniqueTokenLength));
110+
var uniqueTokenSuffix = string.Concat("_", TokenIdGenerator.NewTokenId(uniqueTokenLength));
111111
var uniqueName = string.Concat(tableNameToMakeUnique, uniqueTokenSuffix);
112112

113113
if (uniqueName.Length > MaxTableNameLength)

NetStandard.SqlBulkHelpers/CustomExtensions/StringExtensions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ public static string TruncateToLength(this string str, int length)
1212
public static string ReplaceCaseInsensitive(this string str, string oldValue, string @newValue)
1313
=> Replace(str, oldValue, @newValue, StringComparison.OrdinalIgnoreCase);
1414

15+
public static string AsString(this object obj)
16+
=> obj == null || obj is string ? (string)obj : obj.ToString();
17+
1518
/// <summary>
1619
/// Returns a new string in which all occurrences of a specified string in the current instance are replaced with another
1720
/// specified string according the type of search to use for the specified string.

0 commit comments

Comments
 (0)