diff --git a/.editorconfig b/.editorconfig
index e40916ea..a9b1a8bd 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -23,6 +23,9 @@ csharp_new_line_before_members_in_anonymous_types = true
# Sort using and Import directives with System.* appearing first
dotnet_sort_system_directives_first = false
+## Primary constructors
+dotnet_analyzer_diagnostic.category-Style.severity = none
+
# Avoid "this." if not necessary
dotnet_style_qualification_for_field = false : suggestion
dotnet_style_qualification_for_property = false : suggestion
diff --git a/samples/YesSql.Samples.Hi/Program.cs b/samples/YesSql.Samples.Hi/Program.cs
index 2925eeda..8e0b32dd 100644
--- a/samples/YesSql.Samples.Hi/Program.cs
+++ b/samples/YesSql.Samples.Hi/Program.cs
@@ -7,7 +7,7 @@
namespace YesSql.Samples.Hi
{
- internal class Program
+ internal sealed class Program
{
static void Main(string[] args)
{
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index bb942cdb..0b4b190c 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -37,4 +37,81 @@
+
+
+ latest-Recommended
+
+
+ $(NoWarn);CA1805
+
+
+ $(NoWarn);CA1304;CA1305;CA1310
+
+
+ $(NoWarn);CA1311
+
+
+ $(NoWarn);CA1000
+
+
+ $(NoWarn);CA1848
+
+
+ $(NoWarn);CA1720
+
+
+ $(NoWarn);CA1051
+
+
+ $(NoWarn);CA1200
+
+
+ $(NoWarn);CA1711
+
+
+ $(NoWarn);CA1725
+
+
+ $(NoWarn);CA1716
+
+
+ $(NoWarn);CA1001
+
+
+ $(NoWarn);CA2201
+
+
+ $(NoWarn);CA1707
+
+
+ $(NoWarn);CA1727
+
+
+ $(NoWarn);CA1861
+
+
+ $(NoWarn);NU1603
+
+ $(NoWarn);612
+
+ $(NoWarn);618
+
+ $(NoWarn);CA2211
+
+
+ $(NoWarn);CA1016
+
+
+ $(NoWarn);CA2254
+
+ $(NoWarn);CA2208
+
+
+ $(NoWarn),1573,1591,1712
+
+
+ $(NoWarn);NETSDK1206
+
+
+
diff --git a/src/YesSql.Abstractions/ISqlDialect.cs b/src/YesSql.Abstractions/ISqlDialect.cs
index 0c166e0f..5ee1f00f 100644
--- a/src/YesSql.Abstractions/ISqlDialect.cs
+++ b/src/YesSql.Abstractions/ISqlDialect.cs
@@ -27,7 +27,7 @@ public interface ISqlDialect
void ResetTypeHandlers();
- void AddTypeHandler(Func handler);
+ void AddTypeHandler(Func handler);
///
/// Gets the name of the dialect.
@@ -38,7 +38,7 @@ public interface ISqlDialect
/// Gets the cascade constraint sql statement.
///
string CascadeConstraintsString { get; }
-
+
///
/// Gets the create table sql statement.
///
@@ -64,7 +64,7 @@ public interface ISqlDialect
/// Whether the underlying database support batching.
///
bool SupportsBatching { get; }
-
+
///
/// Whether the dialect support unique queries.
///
@@ -94,7 +94,7 @@ public interface ISqlDialect
/// Gets the Int64 primary key with identity column SQL statement.
///
string LegacyIdentityColumnString { get; }
-
+
///
/// Gets the identity select SQL statement to append to an insert in order to return the last generated identifier.
///
diff --git a/src/YesSql.Abstractions/Indexes/DescribeFor.cs b/src/YesSql.Abstractions/Indexes/DescribeFor.cs
index e376c209..2688feec 100644
--- a/src/YesSql.Abstractions/Indexes/DescribeFor.cs
+++ b/src/YesSql.Abstractions/Indexes/DescribeFor.cs
@@ -88,19 +88,11 @@ public IGroupFor Map(Func> map)
public IReduceFor Group(Expression> group)
{
- var memberExpression = group.Body as MemberExpression;
+ var memberExpression = group.Body as MemberExpression
+ ?? throw new ArgumentException("Group expression is not a valid member of: " + typeof(TIndex).Name);
- if (memberExpression == null)
- {
- throw new ArgumentException("Group expression is not a valid member of: " + typeof(TIndex).Name);
- }
-
- var property = memberExpression.Member as PropertyInfo;
-
- if (property == null)
- {
- throw new ArgumentException("Group expression is not a valid property of: " + typeof(TIndex).Name);
- }
+ var property = memberExpression.Member as PropertyInfo
+ ?? throw new ArgumentException("Group expression is not a valid property of: " + typeof(TIndex).Name);
GroupProperty = property;
diff --git a/src/YesSql.Abstractions/SimplifiedTypeName.cs b/src/YesSql.Abstractions/SimplifiedTypeNameAttribute.cs
similarity index 51%
rename from src/YesSql.Abstractions/SimplifiedTypeName.cs
rename to src/YesSql.Abstractions/SimplifiedTypeNameAttribute.cs
index 0fadbc31..fce2ec52 100644
--- a/src/YesSql.Abstractions/SimplifiedTypeName.cs
+++ b/src/YesSql.Abstractions/SimplifiedTypeNameAttribute.cs
@@ -5,11 +5,12 @@ namespace YesSql
///
/// Use this attribute to provide a custom string representation of a type.
///
- public class SimplifiedTypeName : Attribute
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Delegate)]
+ public class SimplifiedTypeNameAttribute : Attribute
{
public string Name { get; set; }
- public SimplifiedTypeName(string name)
+ public SimplifiedTypeNameAttribute(string name)
{
Name = name;
}
diff --git a/src/YesSql.Core/Commands/BatchCommand.cs b/src/YesSql.Core/Commands/BatchCommand.cs
index d37a9124..53eec3db 100644
--- a/src/YesSql.Core/Commands/BatchCommand.cs
+++ b/src/YesSql.Core/Commands/BatchCommand.cs
@@ -12,7 +12,7 @@ public class BatchCommand : IIndexCommand
public static int DefaultBuilderCapacity = 10 * 1024;
public List Queries { get; set; } = new List();
- public DbCommand Command { get; set; }
+ public DbCommand Command { get; set; }
public List> Actions = new();
public int ExecutionOrder => 0;
diff --git a/src/YesSql.Core/Commands/IndexCommand.cs b/src/YesSql.Core/Commands/IndexCommand.cs
index c0e0b234..67bc7a3b 100644
--- a/src/YesSql.Core/Commands/IndexCommand.cs
+++ b/src/YesSql.Core/Commands/IndexCommand.cs
@@ -110,7 +110,11 @@ protected string Inserts(Type type, ISqlDialect dialect)
for (var i = 0; i < allProperties.Length; i++)
{
var property = allProperties.ElementAt(i);
- sbParameterList.Append("@").Append(property.Name).Append(ParameterSuffix);
+
+ sbParameterList.Append('@')
+ .Append(property.Name)
+ .Append(ParameterSuffix);
+
if (i < allProperties.Length - 1)
{
sbParameterList.Append(", ");
@@ -186,6 +190,6 @@ private static bool IsWriteable(PropertyInfo pi)
public abstract bool AddToBatch(ISqlDialect dialect, List queries, DbCommand batchCommand, List> actions, int index);
- private record CompoundKey(string Dialect, string Type, string Schema, string Prefix, string Collection);
+ private sealed record CompoundKey(string Dialect, string Type, string Schema, string Prefix, string Collection);
}
}
diff --git a/src/YesSql.Core/Data/NullableThumbprintFactory.cs b/src/YesSql.Core/Data/NullableThumbprintFactory.cs
index 4be1d7f8..723ff7fc 100644
--- a/src/YesSql.Core/Data/NullableThumbprintFactory.cs
+++ b/src/YesSql.Core/Data/NullableThumbprintFactory.cs
@@ -9,9 +9,9 @@ namespace YesSql.Data
/// If nullable arguments (including strings) are used, the SQL should vary.
/// This class allows to generate a Thumbprint for each set of nullable compiled query properties.
///
- internal class NullableThumbprintFactory
+ internal sealed class NullableThumbprintFactory
{
- private static Dictionary _discriminatorFactories = new();
+ private static readonly Dictionary _discriminatorFactories = new();
internal static NullableThumbprintBuilder GetNullableThumbprintBuilder(Type type)
{
@@ -32,29 +32,27 @@ internal static NullableThumbprintBuilder GetNullableThumbprintBuilder(Type type
public static long GetNullableThumbprint(object item)
{
- if (item == null)
- {
- throw new ArgumentNullException(nameof(item));
- }
+ ArgumentNullException.ThrowIfNull(item);
var builder = GetNullableThumbprintBuilder(item.GetType());
+
return builder.GetNullableThumbprint(item);
}
}
- internal class NullableThumbprintBuilder
+ internal sealed class NullableThumbprintBuilder
{
- private Type _type;
+ private readonly Type _type;
private static int _globalTypeIndex;
- private long _typeIndex;
+ private readonly long _typeIndex;
private const int MaxTypeIndex = 1 << 16; // 65536 types max, 16 bits for the type
private const int MaxProperties = 48;
- private List _nullableAccessors;
+ private readonly List _nullableAccessors;
public NullableThumbprintBuilder(Type type)
- {
+ {
_type = type;
// Each type gets a unique type index
@@ -96,7 +94,7 @@ private interface INullablePropertyAccessor
bool IsPropertyNull(object obj);
}
- private class NullableAccessor : INullablePropertyAccessor where T : class
+ private sealed class NullableAccessor : INullablePropertyAccessor where T : class
{
private readonly Func _getter;
@@ -111,6 +109,8 @@ bool INullablePropertyAccessor.IsPropertyNull(object obj)
}
}
+ private const long _long1 = 1;
+
///
/// Returns an 64 bits integer representing the unique set of nullable fields as a bit mask. The 16 MSB represent the type, and the 48 LSB represent individual fields
///
@@ -122,14 +122,12 @@ public long GetNullableThumbprint(object o)
{
return mask;
}
-
- const long long1 = 1;
- for (var i= 0; i < _nullableAccessors.Count; i++)
+ for (var i = 0; i < _nullableAccessors.Count; i++)
{
if (_nullableAccessors[i].IsPropertyNull(o))
{
- mask = mask | (long1 << i);
+ mask = mask | (_long1 << i);
}
}
diff --git a/src/YesSql.Core/Data/PropertyAccessorFactory.cs b/src/YesSql.Core/Data/PropertyAccessorFactory.cs
index 8c318072..e75dbb95 100644
--- a/src/YesSql.Core/Data/PropertyAccessorFactory.cs
+++ b/src/YesSql.Core/Data/PropertyAccessorFactory.cs
@@ -9,11 +9,11 @@ namespace YesSql.Data
///
public class PropertyAccessorFactory : IAccessorFactory
{
- const BindingFlags DefaultBindingFlags = BindingFlags.IgnoreCase
- | BindingFlags.Public
- | BindingFlags.Instance
- | BindingFlags.GetProperty
- | BindingFlags.SetProperty
+ const BindingFlags DefaultBindingFlags = BindingFlags.IgnoreCase
+ | BindingFlags.Public
+ | BindingFlags.Instance
+ | BindingFlags.GetProperty
+ | BindingFlags.SetProperty
;
private readonly string _propertyName;
@@ -41,7 +41,7 @@ public IAccessor CreateAccessor(Type tContainer)
var setter = propertyInfo.GetSetMethod(true).CreateDelegate(setType);
Type accessorType = null;
-
+
if (tProperty == typeof(int))
{
accessorType = typeof(IntAccessor<>);
@@ -66,7 +66,7 @@ public IAccessor CreateAccessor(Type tContainer)
/// An accessor to an Int32 Id property
///
///
- internal class IntAccessor : IAccessor
+ internal sealed class IntAccessor : IAccessor
{
private readonly Func _getter;
private readonly Action _setter;
@@ -92,7 +92,7 @@ void IAccessor.Set(object obj, long value)
/// An accessor to an Int64 Id property
///
///
- internal class LongAccessor : IAccessor
+ internal sealed class LongAccessor : IAccessor
{
private readonly Func _getter;
private readonly Action _setter;
diff --git a/src/YesSql.Core/Data/WorkerQueryKey.cs b/src/YesSql.Core/Data/WorkerQueryKey.cs
index 6a347e3a..bafce098 100644
--- a/src/YesSql.Core/Data/WorkerQueryKey.cs
+++ b/src/YesSql.Core/Data/WorkerQueryKey.cs
@@ -64,12 +64,12 @@ public bool Equals(WorkerQueryKey other)
{
return false;
}
-
+
if (_parameters != null || other._parameters != null)
{
return SameParameters(_parameters, other._parameters);
}
-
+
if (_ids != null || other._ids != null)
{
return SameIds(_ids, other._ids);
diff --git a/src/YesSql.Core/Provider/BaseDialect.cs b/src/YesSql.Core/Provider/BaseDialect.cs
index 9e904359..82f9d7a2 100644
--- a/src/YesSql.Core/Provider/BaseDialect.cs
+++ b/src/YesSql.Core/Provider/BaseDialect.cs
@@ -75,7 +75,7 @@ public virtual object TryConvert(object source)
public abstract string Name { get; }
public virtual string InOperator(string values)
{
- if (values.StartsWith("@") && !values.Contains(','))
+ if (values.StartsWith('@') && !values.Contains(','))
{
return " IN " + values;
}
@@ -106,7 +106,7 @@ public virtual string NotInSelectOperator(string values)
public abstract string IdentitySelectString { get; }
public abstract string IdentityLastId { get; }
-
+
public abstract string IdentityColumnString { get; }
public abstract string LegacyIdentityColumnString { get; }
@@ -286,7 +286,7 @@ public void ResetTypeHandlers()
_typeHandlers.Clear();
}
- public void AddTypeHandler(Func handler)
+ public void AddTypeHandler(Func handler)
{
if (!_typeHandlers.TryGetValue(typeof(T), out var handlers))
{
diff --git a/src/YesSql.Core/Provider/ServiceCollectionExtensions.cs b/src/YesSql.Core/Provider/ServiceCollectionExtensions.cs
index e085c3c8..b80b4e3c 100644
--- a/src/YesSql.Core/Provider/ServiceCollectionExtensions.cs
+++ b/src/YesSql.Core/Provider/ServiceCollectionExtensions.cs
@@ -9,15 +9,9 @@ public static IServiceCollection AddDbProvider(
this IServiceCollection services,
Action setupAction)
{
- if (services == null)
- {
- throw new ArgumentNullException(nameof(services));
- }
+ ArgumentNullException.ThrowIfNull(services);
- if (setupAction == null)
- {
- throw new ArgumentNullException(nameof(setupAction));
- }
+ ArgumentNullException.ThrowIfNull(setupAction);
var config = new Configuration();
setupAction.Invoke(config);
diff --git a/src/YesSql.Core/Serialization/DefaultContentSerializer.cs b/src/YesSql.Core/Serialization/DefaultContentSerializer.cs
index 3515a57e..aeb1234b 100644
--- a/src/YesSql.Core/Serialization/DefaultContentSerializer.cs
+++ b/src/YesSql.Core/Serialization/DefaultContentSerializer.cs
@@ -10,8 +10,10 @@ public class DefaultContentSerializer : IContentSerializer
public DefaultContentSerializer()
{
- _options = new();
- _options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
+ _options = new()
+ {
+ DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
+ };
_options.Converters.Add(UtcDateTimeJsonConverter.Instance);
_options.Converters.Add(DynamicJsonConverter.Instance);
}
diff --git a/src/YesSql.Core/Services/DbBlockIdGenerator.cs b/src/YesSql.Core/Services/DbBlockIdGenerator.cs
index 8b95f7e1..8a0d230b 100644
--- a/src/YesSql.Core/Services/DbBlockIdGenerator.cs
+++ b/src/YesSql.Core/Services/DbBlockIdGenerator.cs
@@ -260,7 +260,7 @@ public async Task InitializeCollectionAsync(IConfiguration configuration, string
_ranges[collection] = new Range(collection);
}
- private class Range
+ private sealed class Range
{
public Range(string collection)
{
diff --git a/src/YesSql.Core/Services/DefaultQuery.cs b/src/YesSql.Core/Services/DefaultQuery.cs
index 542c2ee6..04ad5667 100644
--- a/src/YesSql.Core/Services/DefaultQuery.cs
+++ b/src/YesSql.Core/Services/DefaultQuery.cs
@@ -169,6 +169,40 @@ static DefaultQuery()
builder.Append(")");
};
+ MethodMappings[typeof(String).GetMethod("StartsWith", new Type[] { typeof(char) })] = static (query, builder, dialect, expression) =>
+ {
+ builder.Append("(");
+ query.ConvertFragment(builder, expression.Object);
+ builder.Append(" like ");
+ query.ConvertFragment(builder, expression.Arguments[0]);
+ var parameter = query._queryState._sqlBuilder.Parameters[query._queryState._lastParameterName];
+ query._queryState._sqlBuilder.Parameters[query._queryState._lastParameterName] = parameter.ToString() + "%";
+ builder.Append(")");
+ };
+
+ MethodMappings[typeof(String).GetMethod("EndsWith", new Type[] { typeof(char) })] = static (query, builder, dialect, expression) =>
+ {
+ builder.Append("(");
+ query.ConvertFragment(builder, expression.Object);
+ builder.Append(" like ");
+ query.ConvertFragment(builder, expression.Arguments[0]);
+ var parameter = query._queryState._sqlBuilder.Parameters[query._queryState._lastParameterName];
+ query._queryState._sqlBuilder.Parameters[query._queryState._lastParameterName] = "%" + parameter.ToString();
+ builder.Append(")");
+
+ };
+
+ MethodMappings[typeof(String).GetMethod("Contains", new Type[] { typeof(char) })] = static (query, builder, dialect, expression) =>
+ {
+ builder.Append("(");
+ query.ConvertFragment(builder, expression.Object);
+ builder.Append(" like ");
+ query.ConvertFragment(builder, expression.Arguments[0]);
+ var parameter = query._queryState._sqlBuilder.Parameters[query._queryState._lastParameterName];
+ query._queryState._sqlBuilder.Parameters[query._queryState._lastParameterName] = "%" + parameter.ToString() + "%";
+ builder.Append(")");
+ };
+
MethodMappings[typeof(String).GetMethod(nameof(string.Concat), new Type[] { typeof(string[]) })] =
MethodMappings[typeof(String).GetMethod(nameof(string.Concat), new Type[] { typeof(string), typeof(string) })] =
MethodMappings[typeof(String).GetMethod(nameof(string.Concat), new Type[] { typeof(string), typeof(string), typeof(string) })] =
@@ -790,7 +824,7 @@ public void ConvertFragment(IStringBuilder builder, Expression expression)
var methodInfo = methodCallExpression.Method;
Action action;
if (MethodMappings.TryGetValue(methodInfo, out action)
- || MethodMappings.TryGetValue(methodInfo.GetGenericMethodDefinition(), out action))
+ || (methodInfo.IsGenericMethod && MethodMappings.TryGetValue(methodInfo.GetGenericMethodDefinition(), out action)))
{
action(this, builder, _dialect, methodCallExpression);
}
@@ -874,7 +908,7 @@ public void ConvertPredicate(IStringBuilder builder, Expression expression)
///
///
///
- private bool IsParameterBased(Expression expression)
+ private static bool IsParameterBased(Expression expression)
{
switch (expression.NodeType)
{
@@ -1396,12 +1430,12 @@ private string GetDeduplicatedQuery()
sqlBuilder.Selector(selector);
sqlBuilder.GroupBy(selector);
- var aggregates = _query._dialect.GetAggregateOrders(sqlBuilder.GetSelectors().ToList(), sqlBuilder.GetOrders().ToList());
+ var results = _query._dialect.GetAggregateOrders(sqlBuilder.GetSelectors().ToList(), sqlBuilder.GetOrders().ToList());
if (sqlBuilder.HasOrder)
{
sqlBuilder.ClearOrder();
- foreach (var result in aggregates)
+ foreach (var result in results)
{
sqlBuilder.AddSelector(", ");
sqlBuilder.AddSelector(result.aggregate);
@@ -1423,7 +1457,7 @@ private string GetDeduplicatedQuery()
if (sqlBuilder.HasOrder)
{
- sql += $" ORDER BY {string.Join(", ", aggregates.Select(x => x.alias).ToList())}";
+ sql += $" ORDER BY {string.Join(", ", results.Select(x => x.alias).ToList())}";
}
return sql;
@@ -1500,7 +1534,7 @@ async ValueTask> IQuery.AllAsync(params Func, ValueTask ComposeQuery(Func, IQuery>[] predicates, CompositeNode predicate)
+ private Query ComposeQuery(Func, IQuery>[] predicates, CompositeNode predicate)
{
_query._queryState._currentPredicate.Children.Add(predicate);
diff --git a/src/YesSql.Core/Services/IndexProviderRegisterExtensions.cs b/src/YesSql.Core/Services/IndexProviderRegisterExtensions.cs
index d40f6d85..f575cd61 100644
--- a/src/YesSql.Core/Services/IndexProviderRegisterExtensions.cs
+++ b/src/YesSql.Core/Services/IndexProviderRegisterExtensions.cs
@@ -17,10 +17,10 @@ public static IStore RegisterIndexes(this IStore store, IIndexProvider indexProv
{
if (indexProvider != null)
{
- return store.RegisterIndexes(new[] { indexProvider }, collection);
+ return store.RegisterIndexes([indexProvider], collection);
}
- return store.RegisterIndexes(new IIndexProvider[0], collection);
+ return store.RegisterIndexes([], collection);
}
public static IStore RegisterIndexes(this IStore store, Type type, string collection = null)
@@ -37,7 +37,7 @@ public static IStore RegisterIndexes(this IStore store, IEnumerable types,
store.RegisterIndexes(type, collection);
}
- return store.RegisterIndexes(new IIndexProvider[0], collection);
+ return store.RegisterIndexes([], collection);
}
public static IStore RegisterIndexes(this IStore store, Assembly assembly, string collection = null)
diff --git a/src/YesSql.Core/Services/PredicateNodes.cs b/src/YesSql.Core/Services/PredicateNodes.cs
index f30640e0..73638f2a 100644
--- a/src/YesSql.Core/Services/PredicateNodes.cs
+++ b/src/YesSql.Core/Services/PredicateNodes.cs
@@ -16,7 +16,7 @@ internal abstract class CompositeNode : PredicateNode
public List Children = new();
}
- internal class AndNode : CompositeNode
+ internal sealed class AndNode : CompositeNode
{
public override void Build(RentedStringBuilder builder)
{
@@ -48,14 +48,16 @@ public override void Build(RentedStringBuilder builder)
public override PredicateNode Clone()
{
var children = Children.Select(x => x.Clone()).ToList();
- var clone = new AndNode();
- clone.Children = children;
+ var clone = new AndNode
+ {
+ Children = children
+ };
return clone;
}
}
- internal class OrNode : CompositeNode
+ internal sealed class OrNode : CompositeNode
{
public override void Build(RentedStringBuilder builder)
{
@@ -96,7 +98,7 @@ public override PredicateNode Clone()
}
}
- internal class FilterNode : CompositeNode
+ internal sealed class FilterNode : CompositeNode
{
public FilterNode(string filter)
{
diff --git a/src/YesSql.Core/Services/TypeService.cs b/src/YesSql.Core/Services/TypeService.cs
index eb1a73e4..7792496f 100644
--- a/src/YesSql.Core/Services/TypeService.cs
+++ b/src/YesSql.Core/Services/TypeService.cs
@@ -22,7 +22,7 @@ public string this[Type t]
return "dynamic";
}
- var customName = typeInfo.GetCustomAttribute();
+ var customName = typeInfo.GetCustomAttribute();
var calculatedName = string.IsNullOrEmpty(customName?.Name) ? $"{type.FullName}, {typeInfo.Assembly.GetName().Name}" : customName.Name;
nameTypes[calculatedName] = t;
diff --git a/src/YesSql.Core/Session.cs b/src/YesSql.Core/Session.cs
index 0544f024..a3647505 100644
--- a/src/YesSql.Core/Session.cs
+++ b/src/YesSql.Core/Session.cs
@@ -255,10 +255,7 @@ private static void DetachInternal(object entity, SessionState state)
private async Task SaveEntityAsync(object entity, string collection)
{
- if (entity == null)
- {
- throw new ArgumentNullException(nameof(entity));
- }
+ ArgumentNullException.ThrowIfNull(entity);
if (entity is Document)
{
@@ -312,17 +309,14 @@ private async Task SaveEntityAsync(object entity, string collection)
private async Task UpdateEntityAsync(object entity, bool tracked, string collection)
{
- if (entity == null)
- {
- throw new ArgumentNullException(nameof(entity));
- }
+ ArgumentNullException.ThrowIfNull(entity);
if (entity is Document)
{
throw new ArgumentException("A document should not be saved explicitly");
}
- if (entity is IIndex index)
+ if (entity is IIndex)
{
throw new ArgumentException("An index should not be saved explicitly");
}
@@ -349,7 +343,7 @@ private async Task UpdateEntityAsync(object entity, bool tracked, string collect
// if the document has already been updated or saved with this session (auto or intentional flush), ensure it has
// been changed before doing another query
- if (tracked && string.Equals(newContent, oldDoc.Content))
+ if (tracked && string.Equals(newContent, oldDoc.Content, StringComparison.Ordinal))
{
return;
}
@@ -445,10 +439,7 @@ public void Delete(object obj, string collection = null)
private async Task DeleteEntityAsync(object obj, string collection)
{
- if (obj == null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
+ ArgumentNullException.ThrowIfNull(obj);
if (obj is IIndex)
{
@@ -459,11 +450,8 @@ private async Task DeleteEntityAsync(object obj, string collection)
if (!state.IdentityMap.TryGetDocumentId(obj, out var id))
{
- var accessor = _store.GetIdAccessor(obj.GetType());
- if (accessor == null)
- {
- throw new InvalidOperationException("Could not delete object as it doesn't have an Id property");
- }
+ var accessor = _store.GetIdAccessor(obj.GetType())
+ ?? throw new InvalidOperationException("Could not delete object as it doesn't have an Id property");
id = accessor.Get(obj);
}
@@ -604,10 +592,7 @@ public IQuery Query(string collection = null)
public IQuery ExecuteQuery(ICompiledQuery compiledQuery, string collection = null) where T : class
{
- if (compiledQuery == null)
- {
- throw new ArgumentNullException(nameof(compiledQuery));
- }
+ ArgumentNullException.ThrowIfNull(compiledQuery);
var compiledQueryType = compiledQuery.GetType();
@@ -627,10 +612,12 @@ public IQuery ExecuteQuery(ICompiledQuery compiledQuery, string collect
private void CheckDisposed()
{
+#pragma warning disable CA1513 // Use ObjectDisposedException throw helper
if (_disposed)
{
throw new ObjectDisposedException(nameof(Session));
}
+#pragma warning restore CA1513 // Use ObjectDisposedException throw helper
}
~Session()
@@ -700,7 +687,7 @@ private async Task FlushInternalAsync(bool saving)
{
EnterAsyncExecution();
}
-
+
try
{
// saving all tracked entities
@@ -789,7 +776,7 @@ private async Task FlushInternalAsync(bool saving)
if (!saving)
{
ExitAsyncExecution();
- }
+ }
}
}
@@ -1135,13 +1122,8 @@ private async Task ReduceAsync()
// reduce over the two objects
var reductions = new[] { dbIndex, index };
- var groupedReductions = reductions.GroupBy(descriptorGroup).SingleOrDefault();
-
- if (groupedReductions == null)
- {
- throw new InvalidOperationException(
- "The grouping on the db and in memory set should have resulted in a unique result");
- }
+ var groupedReductions = reductions.GroupBy(descriptorGroup).SingleOrDefault()
+ ?? throw new InvalidOperationException("The grouping on the db and in memory set should have resulted in a unique result");
index = descriptor.Reduce(groupedReductions);
diff --git a/src/YesSql.Core/SessionState.cs b/src/YesSql.Core/SessionState.cs
index 96548d79..5f844569 100644
--- a/src/YesSql.Core/SessionState.cs
+++ b/src/YesSql.Core/SessionState.cs
@@ -4,7 +4,7 @@
namespace YesSql
{
- internal class SessionState
+ internal sealed class SessionState
{
internal Dictionary> _maps;
public Dictionary> Maps => _maps ??= new Dictionary>();
diff --git a/src/YesSql.Core/Sql/BaseComandInterpreter.cs b/src/YesSql.Core/Sql/BaseComandInterpreter.cs
index 4c9311e3..4ef1922a 100644
--- a/src/YesSql.Core/Sql/BaseComandInterpreter.cs
+++ b/src/YesSql.Core/Sql/BaseComandInterpreter.cs
@@ -305,7 +305,7 @@ private void Run(StringBuilder builder, ICreateColumnCommand command)
? _dialect.NullColumnString
: string.Empty);
- // append unique if handled, otherwise at the end of the satement
+ // append unique if handled, otherwise at the end of the statement
if (command.IsUnique && _dialect.SupportsUnique)
{
builder.Append(" unique");
@@ -319,7 +319,7 @@ private void Run(StringBuilder builder, ICreateColumnCommand command)
///
///
///
- private string GetRawColumnName(string name)
+ private static string GetRawColumnName(string name)
{
var index = name.IndexOf('(');
diff --git a/src/YesSql.Core/Sql/SqlBuilder.cs b/src/YesSql.Core/Sql/SqlBuilder.cs
index eb53e886..b1608f2f 100644
--- a/src/YesSql.Core/Sql/SqlBuilder.cs
+++ b/src/YesSql.Core/Sql/SqlBuilder.cs
@@ -425,23 +425,25 @@ public virtual string ToSqlString()
public ISqlBuilder Clone()
{
- var clone = new SqlBuilder(_tablePrefix, _dialect);
-
- clone._clause = _clause;
- clone._table = _table;
-
- clone._select = _select == null ? null : new List(_select);
- clone._from = _from == null ? null : new List(_from);
- clone._join = _join == null ? null : new List(_join);
- clone._where = _where == null ? null : new List(_where);
- clone._group = _group == null ? null : new List(_group);
- clone._having = _having == null ? null : new List(_having);
- clone._order = _order == null ? null : new List(_order);
- clone._trail = _trail == null ? null : new List(_trail);
- clone._skip = _skip;
- clone._count = _count;
-
- clone.Parameters = new Dictionary(Parameters);
+ var clone = new SqlBuilder(_tablePrefix, _dialect)
+ {
+ _clause = _clause,
+ _table = _table,
+
+ _select = _select == null ? null : new List(_select),
+ _from = _from == null ? null : new List(_from),
+ _join = _join == null ? null : new List(_join),
+ _where = _where == null ? null : new List(_where),
+ _group = _group == null ? null : new List(_group),
+ _having = _having == null ? null : new List(_having),
+ _order = _order == null ? null : new List(_order),
+ _trail = _trail == null ? null : new List(_trail),
+ _skip = _skip,
+ _count = _count,
+
+ Parameters = new Dictionary(Parameters)
+ };
+
return clone;
}
}
diff --git a/src/YesSql.Core/Store.cs b/src/YesSql.Core/Store.cs
index 904ff779..d4bcf529 100644
--- a/src/YesSql.Core/Store.cs
+++ b/src/YesSql.Core/Store.cs
@@ -209,7 +209,9 @@ private void ValidateConfiguration()
public ISession CreateSession(bool withTracking = true)
=> new Session(this, withTracking);
+#pragma warning disable CA1816 // Dispose methods should call SuppressFinalize
public void Dispose()
+#pragma warning restore CA1816 // Dispose methods should call SuppressFinalize
{
}
@@ -224,10 +226,7 @@ public IAccessor GetVersionAccessor(Type tContainer)
///
public IEnumerable Describe(Type target, string collection)
{
- if (target == null)
- {
- throw new ArgumentNullException(nameof(target));
- }
+ ArgumentNullException.ThrowIfNull(target);
var cacheKey = string.IsNullOrEmpty(collection)
? target.FullName
diff --git a/src/YesSql.Core/Utils/HashHelper.cs b/src/YesSql.Core/Utils/HashHelper.cs
index 8ce421df..6e0a72ba 100644
--- a/src/YesSql.Core/Utils/HashHelper.cs
+++ b/src/YesSql.Core/Utils/HashHelper.cs
@@ -20,25 +20,22 @@ public static string HashName(string prefix, string name)
throw new ArgumentNullException("A prefix is required");
}
- using (var hash = SHA256.Create())
- {
- var bytes = Encoding.UTF8.GetBytes(name);
- var hashed = hash.ComputeHash(bytes);
+ var bytes = Encoding.UTF8.GetBytes(name);
+ var hashed = SHA256.HashData(bytes);
- var long1 = BitConverter.ToInt64(hashed, 0);
- var long2 = BitConverter.ToInt64(hashed, 8);
- var long3 = BitConverter.ToInt64(hashed, 16);
- var long4 = BitConverter.ToInt64(hashed, 24);
+ var long1 = BitConverter.ToInt64(hashed, 0);
+ var long2 = BitConverter.ToInt64(hashed, 8);
+ var long3 = BitConverter.ToInt64(hashed, 16);
+ var long4 = BitConverter.ToInt64(hashed, 24);
- return prefix + ToBase32(long1, long2, long3, long4);
- }
+ return prefix + ToBase32(long1, long2, long3, long4);
}
private static string ToBase32(long long1, long long2, long long3, long long4)
{
var charBuffer = new char[52];
- int i = 0;
+ var i = 0;
i = EncodeSegment(charBuffer, i, long1);
@@ -49,7 +46,7 @@ private static string ToBase32(long long1, long long2, long long3, long long4)
EncodeSegment(charBuffer, i, long4);
return new string(charBuffer);
- }
+ }
private static int EncodeSegment(char[] charBuffer, int startIndex, long lng)
{
diff --git a/src/YesSql.Provider.MySql/MySqlCommandInterpreter.cs b/src/YesSql.Provider.MySql/MySqlCommandInterpreter.cs
index a5fadd34..891b2916 100644
--- a/src/YesSql.Provider.MySql/MySqlCommandInterpreter.cs
+++ b/src/YesSql.Provider.MySql/MySqlCommandInterpreter.cs
@@ -48,7 +48,7 @@ public override void Run(StringBuilder builder, IAlterColumnCommand command)
if (command.Default != null)
{
- builder2.Append(" set default ").Append(_dialect.GetSqlValue(command.Default)).Append(" ");
+ builder2.Append(" set default ").Append(_dialect.GetSqlValue(command.Default)).Append(' ');
}
// result
diff --git a/src/YesSql.Provider.MySql/MySqlDbProviderOptionsExtensions.cs b/src/YesSql.Provider.MySql/MySqlDbProviderOptionsExtensions.cs
index 3c9ea99e..a14041d4 100644
--- a/src/YesSql.Provider.MySql/MySqlDbProviderOptionsExtensions.cs
+++ b/src/YesSql.Provider.MySql/MySqlDbProviderOptionsExtensions.cs
@@ -1,6 +1,6 @@
+using MySqlConnector;
using System;
using System.Data;
-using MySqlConnector;
namespace YesSql.Provider.MySql
{
@@ -20,10 +20,7 @@ public static IConfiguration UseMySql(
IsolationLevel isolationLevel,
string schema = null)
{
- if (configuration == null)
- {
- throw new ArgumentNullException(nameof(configuration));
- }
+ ArgumentNullException.ThrowIfNull(configuration);
if (string.IsNullOrWhiteSpace(connectionString))
{
diff --git a/src/YesSql.Provider.PostgreSql/PostgreSqlDbProviderOptionsExtensions.cs b/src/YesSql.Provider.PostgreSql/PostgreSqlDbProviderOptionsExtensions.cs
index 3a9d62ff..25f48e8c 100644
--- a/src/YesSql.Provider.PostgreSql/PostgreSqlDbProviderOptionsExtensions.cs
+++ b/src/YesSql.Provider.PostgreSql/PostgreSqlDbProviderOptionsExtensions.cs
@@ -20,10 +20,7 @@ public static IConfiguration UsePostgreSql(
IsolationLevel isolationLevel,
string schema = null)
{
- if (configuration == null)
- {
- throw new ArgumentNullException(nameof(configuration));
- }
+ ArgumentNullException.ThrowIfNull(configuration);
if (string.IsNullOrWhiteSpace(connectionString))
{
diff --git a/src/YesSql.Provider.SqlServer/SqlServerDbProviderOptionsExtensions.cs b/src/YesSql.Provider.SqlServer/SqlServerDbProviderOptionsExtensions.cs
index 12a4fd5f..04b714db 100644
--- a/src/YesSql.Provider.SqlServer/SqlServerDbProviderOptionsExtensions.cs
+++ b/src/YesSql.Provider.SqlServer/SqlServerDbProviderOptionsExtensions.cs
@@ -1,6 +1,6 @@
+using Microsoft.Data.SqlClient;
using System;
using System.Data;
-using Microsoft.Data.SqlClient;
namespace YesSql.Provider.SqlServer
{
@@ -20,10 +20,7 @@ public static IConfiguration UseSqlServer(
IsolationLevel isolationLevel,
string schema = null)
{
- if (configuration == null)
- {
- throw new ArgumentNullException(nameof(configuration));
- }
+ ArgumentNullException.ThrowIfNull(configuration);
if (string.IsNullOrWhiteSpace(connectionString))
{
diff --git a/src/YesSql.Provider.Sqlite/SqliteDbProviderOptionsExtensions.cs b/src/YesSql.Provider.Sqlite/SqliteDbProviderOptionsExtensions.cs
index 43508951..dc9d7771 100644
--- a/src/YesSql.Provider.Sqlite/SqliteDbProviderOptionsExtensions.cs
+++ b/src/YesSql.Provider.Sqlite/SqliteDbProviderOptionsExtensions.cs
@@ -11,8 +11,8 @@ public static IConfiguration UseSqLite(
string connectionString)
{
return UseSqLite(
- configuration,
- connectionString,
+ configuration,
+ connectionString,
IsolationLevel.Serializable);
}
@@ -21,10 +21,7 @@ public static IConfiguration UseSqLite(
string connectionString,
IsolationLevel isolationLevel)
{
- if (configuration == null)
- {
- throw new ArgumentNullException(nameof(configuration));
- }
+ ArgumentNullException.ThrowIfNull(configuration);
if (string.IsNullOrWhiteSpace(connectionString))
{
diff --git a/test/YesSql.Tests/CoreTests.cs b/test/YesSql.Tests/CoreTests.cs
index ff537ef6..6e097749 100644
--- a/test/YesSql.Tests/CoreTests.cs
+++ b/test/YesSql.Tests/CoreTests.cs
@@ -53,7 +53,7 @@ public async Task InitializeAsync()
await _store.InitializeCollectionAsync("Col1");
_store.TypeNames[typeof(Person)] = "People";
- await CreateTablesAsync(_configuration);
+ await CoreTests.CreateTablesAsync(_configuration);
}
else
{
@@ -204,7 +204,7 @@ protected virtual Task OnCleanDatabaseAsync(SchemaBuilder builder, DbTransaction
protected virtual Task OnClearTablesAsync(DbConnection connection)
=> Task.CompletedTask;
- public async Task CreateTablesAsync(IConfiguration configuration)
+ public static async Task CreateTablesAsync(IConfiguration configuration)
{
await using var connection = configuration.ConnectionFactory.CreateConnection();
await connection.OpenAsync();
@@ -1346,11 +1346,11 @@ public async Task ShouldQueryInnerSelect()
await using (var session = _store.CreateSession())
{
- Assert.Equal(1, await session.Query().Where(x => x.Name.IsIn(y => y.SomeName, y => y.SomeName.StartsWith("B") || y.SomeName.StartsWith("C"))).CountAsync());
- Assert.Equal(2, await session.Query().Where(x => x.Name.IsIn(y => y.SomeName, y => y.SomeName.StartsWith("B") || y.SomeName.Contains("lo"))).CountAsync());
+ Assert.Equal(1, await session.Query().Where(x => x.Name.IsIn(y => y.SomeName, y => y.SomeName.StartsWith('B') || y.SomeName.StartsWith('C'))).CountAsync());
+ Assert.Equal(2, await session.Query().Where(x => x.Name.IsIn(y => y.SomeName, y => y.SomeName.StartsWith('B') || y.SomeName.Contains("lo"))).CountAsync());
- Assert.Equal(1, await session.Query().Where(x => x.Name.IsNotIn(y => y.SomeName, y => y.SomeName.StartsWith("B") || y.SomeName.StartsWith("C"))).CountAsync());
- Assert.Equal(0, await session.Query().Where(x => x.Name.IsNotIn(y => y.SomeName, y => y.SomeName.StartsWith("B") || y.SomeName.Contains("lo"))).CountAsync());
+ Assert.Equal(1, await session.Query().Where(x => x.Name.IsNotIn(y => y.SomeName, y => y.SomeName.StartsWith('B') || y.SomeName.StartsWith('C'))).CountAsync());
+ Assert.Equal(0, await session.Query().Where(x => x.Name.IsNotIn(y => y.SomeName, y => y.SomeName.StartsWith('B') || y.SomeName.Contains("lo"))).CountAsync());
}
}
@@ -1498,7 +1498,7 @@ public async Task ShouldQueryWithLike()
Assert.Equal(2, await session.Query().Where(x => x.Name.IsLike("%l%")).CountAsync());
Assert.Equal(1, await session.Query().Where(x => x.Name.IsNotLike("%B%")).CountAsync());
- Assert.Equal(2, await session.Query().Where(x => x.Name.Contains("l")).CountAsync());
+ Assert.Equal(2, await session.Query().Where(x => x.Name.Contains('l')).CountAsync());
Assert.Equal(1, await session.Query().Where(x => x.Name.NotContains("B")).CountAsync());
}
}
@@ -1966,19 +1966,19 @@ public async Task ShouldOrderJoinedMapIndexes()
await using (var session = _store.CreateSession())
{
Assert.Equal(2, await session.Query().For()
- .With(x => x.SomeName.StartsWith("S"))
+ .With(x => x.SomeName.StartsWith('S'))
.With(x => x.Age == 2)
.CountAsync());
Assert.Equal("Scott", (await session.Query().For()
- .With(x => x.SomeName.StartsWith("S"))
+ .With(x => x.SomeName.StartsWith('S'))
.OrderBy(x => x.SomeName)
.With(x => x.Age == 2)
.FirstOrDefaultAsync())
.Firstname);
Assert.Equal("Steve", (await session.Query().For()
- .With(x => x.SomeName.StartsWith("S"))
+ .With(x => x.SomeName.StartsWith('S'))
.OrderByDescending(x => x.SomeName)
.With(x => x.Age == 2)
.FirstOrDefaultAsync())
@@ -2108,9 +2108,9 @@ public async Task JoinOrderShouldNotMatter()
await using (var session = _store.CreateSession())
{
Assert.Equal("Steve", (await session.Query().For()
- .With(x => x.SomeName.StartsWith("S"))
+ .With(x => x.SomeName.StartsWith('S'))
.With(x => x.Age == 2)
- .With(x => x.SomeName.EndsWith("e"))
+ .With(x => x.SomeName.EndsWith('e'))
.FirstOrDefaultAsync()).Firstname);
}
}
@@ -2752,7 +2752,7 @@ public async Task AutoflushCanHappenMultipleTimes()
}
[Fact]
- public async Task ChangesAfterAutoflushAreSaved()
+ public async Task ChangesAfterAutoFlushAreSaved()
{
_store.RegisterIndexes();
@@ -4180,9 +4180,9 @@ public async Task ShouldQueryInnerSelectWithCollection()
Assert.Equal(1, await session.Query(x => x.Name == "Bill", "Col1").CountAsync());
Assert.Equal(1, await session.Query(x => x.Lastname == "Gates", "Col1").CountAsync());
- Assert.Equal(1, await session.Query(collection: "Col1").Where(x => x.Name.IsIn(y => y.Firstname, y => y.Lastname.StartsWith("G"))).CountAsync());
+ Assert.Equal(1, await session.Query(collection: "Col1").Where(x => x.Name.IsIn(y => y.Firstname, y => y.Lastname.StartsWith('G'))).CountAsync());
- Assert.Equal(0, await session.Query(collection: "Col1").Where(x => x.Name.IsNotIn(y => y.Firstname, y => y.Lastname.StartsWith("G") || y.Lastname.StartsWith("M"))).CountAsync());
+ Assert.Equal(0, await session.Query(collection: "Col1").Where(x => x.Name.IsNotIn(y => y.Firstname, y => y.Lastname.StartsWith('G') || y.Lastname.StartsWith('M'))).CountAsync());
Assert.Equal(2, await session.Query(collection: "Col1").Where(x => x.Name.IsInAny(y => y.Firstname)).CountAsync());
Assert.Equal(0, await session.Query(collection: "Col1").Where(x => x.Name.IsNotInAny(y => y.Firstname)).CountAsync());
@@ -6044,13 +6044,14 @@ public async Task AllDataTypesShouldBeQueryableWithProperties()
await using (var session = _store.CreateSession())
{
- var index = new TypesIndex();
-
- index.ValueDateTime = valueDateTime;
- index.ValueGuid = valueGuid;
- index.ValueBool = valueBool;
- index.ValueDateTimeOffset = valueDateTimeOffset;
- index.ValueTimeSpan = valueTimeSpan;
+ var index = new TypesIndex
+ {
+ ValueDateTime = valueDateTime,
+ ValueGuid = valueGuid,
+ ValueBool = valueBool,
+ ValueDateTimeOffset = valueDateTimeOffset,
+ ValueTimeSpan = valueTimeSpan
+ };
((IIndex)index).AddDocument(new Document { Id = dummy.Id });
@@ -6108,13 +6109,14 @@ public async Task AllDataTypesShouldBeQueryableWithConstants()
await using (var session = _store.CreateSession())
{
- var index = new TypesIndex();
-
- index.ValueDateTime = valueDateTime;
- index.ValueGuid = valueGuid;
- index.ValueBool = valueBool;
- index.ValueDateTimeOffset = valueDateTimeOffset;
- index.ValueTimeSpan = valueTimeSpan;
+ var index = new TypesIndex
+ {
+ ValueDateTime = valueDateTime,
+ ValueGuid = valueGuid,
+ ValueBool = valueBool,
+ ValueDateTimeOffset = valueDateTimeOffset,
+ ValueTimeSpan = valueTimeSpan
+ };
((IIndex)index).AddDocument(new Document { Id = dummy.Id });
diff --git a/test/YesSql.Tests/DecimalPrecisionAndScaleDataGenerator.cs b/test/YesSql.Tests/DecimalPrecisionAndScaleDataGenerator.cs
index 435abfa8..0d8a541d 100644
--- a/test/YesSql.Tests/DecimalPrecisionAndScaleDataGenerator.cs
+++ b/test/YesSql.Tests/DecimalPrecisionAndScaleDataGenerator.cs
@@ -3,7 +3,7 @@
namespace YesSql.Tests
{
- internal class DecimalPrecisionAndScaleDataGenerator : TheoryData
+ internal sealed class DecimalPrecisionAndScaleDataGenerator : TheoryData
{
public DecimalPrecisionAndScaleDataGenerator()
{