Skip to content

Commit c2765aa

Browse files
magnusbakken-zetadisplaymsallin
authored andcommitted
More changes for default collations.
- Changed CollateAttribute to use Collation internally. - Throw an exception when CollateAttribute has been used on a non-string property. - Added a line about default collations to the readme.
1 parent 1212374 commit c2765aa

File tree

5 files changed

+57
-40
lines changed

5 files changed

+57
-40
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ The following features are supported:
2727
- Index (Decorate columns with the `Index` attribute. Indices are automatically created for foreign keys by default. To prevent this you can remove the convention `ForeignKeyIndexConvention`)
2828
- Unique constraint (Decorate columns with the `UniqueAttribute`, which is part of this library)
2929
- Collate constraint (Decorate columns with the `CollateAttribute`, which is part of this library. Use `CollationFunction.Custom` to specify a own collation function.)
30+
- Default collation (pass an instance of Collation as constructor parameter for an initializer to specify a default collation).
3031
- SQL default value (Decorate columns with the `SqlDefaultValueAttribute`, which is part of this library)
3132

3233
## Install

SQLite.CodeFirst.Test/IntegrationTests/SqlGenerationDefaultCollationTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public void SqliteSqlGeneratorWithDefaultCollationTest()
5757
// This is important! Else the in memory database will not work.
5858
connection.Open();
5959

60-
var defaultCollation = new Collation() { CollationFunction = CollationFunction.Custom, Function = "custom_collate" };
60+
var defaultCollation = new Collation() { Function = CollationFunction.Custom, CustomFunction = "custom_collate" };
6161
using (var context = new DummyDbContext(connection, defaultCollation))
6262
{
6363
// ReSharper disable once UnusedVariable

SQLite.CodeFirst/Internal/Builder/ColumnStatementCollectionBuilder.cs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Data.Entity.Core.Metadata.Edm;
34
using System.Linq;
45
using SQLite.CodeFirst.Extensions;
@@ -77,17 +78,23 @@ private static void AddNullConstraintIfNecessary(EdmProperty property, ColumnSta
7778

7879
private static void AddCollationConstraintIfNecessary(EdmProperty property, ColumnStatement columnStatement, Collation defaultCollation)
7980
{
80-
if (property.PrimitiveType.PrimitiveTypeKind != PrimitiveTypeKind.String)
81+
var collateAttribute = property.GetCustomAnnotation<CollateAttribute>();
82+
if (property.PrimitiveType.PrimitiveTypeKind == PrimitiveTypeKind.String)
8183
{
82-
return;
84+
// The column is a string type. Check if we have an explicit or default collation.
85+
// If we have both, the explicitly chosen collation takes precedence.
86+
var value = collateAttribute == null ? defaultCollation : collateAttribute.Collation;
87+
if (value != null)
88+
{
89+
columnStatement.ColumnConstraints.Add(new CollateConstraint { CollationFunction = value.Function, CustomCollationFunction = value.CustomFunction });
90+
}
8391
}
84-
85-
var collateAttribute = property.GetCustomAnnotation<CollateAttribute>();
86-
var value = collateAttribute == null ? defaultCollation : collateAttribute.CollationData;
87-
88-
if (value != null)
92+
else if (collateAttribute != null)
8993
{
90-
columnStatement.ColumnConstraints.Add(new CollateConstraint { CollationFunction = value.CollationFunction, CustomCollationFunction = value.Function });
94+
// Only string columns can be explicitly decorated with CollateAttribute.
95+
var name = $"{property.DeclaringType.Name}.{property.Name}";
96+
var errorMessage = $"CollateAttribute cannot be used on non-string property: {name} (underlying type is {property.PrimitiveType.PrimitiveTypeKind})";
97+
throw new InvalidOperationException(errorMessage);
9198
}
9299
}
93100

SQLite.CodeFirst/Public/Attributes/CollateAttribute.cs

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,39 +11,20 @@ namespace SQLite.CodeFirst
1111
public sealed class CollateAttribute : Attribute
1212
{
1313
public CollateAttribute()
14-
: this(CollationFunction.None)
1514
{
15+
Collation = new Collation();
1616
}
1717

18-
public CollateAttribute(CollationFunction collation)
19-
: this(collation, null)
18+
public CollateAttribute(CollationFunction function)
2019
{
20+
Collation = new Collation(function);
2121
}
2222

23-
public CollateAttribute(CollationFunction collation, string function)
23+
public CollateAttribute(CollationFunction function, string customFunction)
2424
{
25-
if (collation != CollationFunction.Custom && !string.IsNullOrEmpty(function))
26-
{
27-
throw new ArgumentException("If the collation is not set to CollationFunction.Custom a function must not be specified.", nameof(function));
28-
}
29-
30-
if (collation == CollationFunction.Custom && string.IsNullOrEmpty(function))
31-
{
32-
throw new ArgumentException("If the collation is set to CollationFunction.Custom a function must be specified.", nameof(function));
33-
}
34-
35-
Collation = collation;
36-
Function = function;
37-
CollationData = new Collation() { CollationFunction = collation, Function = function };
25+
Collation = new Collation(function, customFunction);
3826
}
3927

40-
public CollationFunction Collation { get; }
41-
42-
/// <summary>
43-
/// The name of the custom collating function to use (CollationFunction.Custom).
44-
/// </summary>
45-
public string Function { get; }
46-
47-
public Collation CollationData { get; }
28+
public Collation Collation { get; }
4829
}
4930
}
Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,46 @@
1-
namespace SQLite.CodeFirst
1+
using System;
2+
3+
namespace SQLite.CodeFirst
24
{
35
/// <summary>
46
/// This class can be used to specify the default collation for the database. Explicit Collate attributes will take precendence.
57
/// When SQLite compares two strings, it uses a collating sequence or collating function (two words for the same thing)
6-
/// to determine which string is greater or if the two strings are equal. SQLite has three built-in collating functions (see <see cref="CollationFunction"/>).
7-
/// Set <see cref="CollationFunction"/> to <see cref="CollationFunction.Custom"/> and specify the name using the function parameter.
8+
/// to determine which string is greater or if the two strings are equal. SQLite has three built-in collating functions (see <see cref="Function"/>).
9+
/// Set <see cref="Function"/> to <see cref="CollationFunction.Custom"/> and specify the name using the function parameter.
810
/// </summary>
911
public class Collation
1012
{
11-
public CollationFunction CollationFunction { get; set; }
13+
public Collation()
14+
: this(CollationFunction.None)
15+
{
16+
}
17+
18+
public Collation(CollationFunction function)
19+
: this(function, null)
20+
{
21+
}
22+
23+
public Collation(CollationFunction function, string customFunction)
24+
{
25+
if (function != CollationFunction.Custom && !string.IsNullOrEmpty(customFunction))
26+
{
27+
throw new ArgumentException("If the collation is not set to CollationFunction.Custom a function must not be specified.", nameof(function));
28+
}
29+
30+
if (function == CollationFunction.Custom && string.IsNullOrEmpty(customFunction))
31+
{
32+
throw new ArgumentException("If the collation is set to CollationFunction.Custom a function must be specified.", nameof(function));
33+
}
34+
35+
CustomFunction = customFunction;
36+
Function = function;
37+
}
38+
39+
public CollationFunction Function { get; set; }
1240

1341
/// <summary>
1442
/// The name of the custom collating function to use (CollationFunction.Custom).
1543
/// </summary>
16-
public string Function { get; set; }
44+
public string CustomFunction { get; set; }
1745
}
1846
}

0 commit comments

Comments
 (0)