Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit 4f6d602

Browse files
committed
2 parents eaac537 + 697f6b1 commit 4f6d602

File tree

3 files changed

+320
-105
lines changed

3 files changed

+320
-105
lines changed

src/ServiceStack.OrmLite.SqlServer/SqlServer2012OrmLiteDialectProvider.cs

Lines changed: 159 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
using System.Data;
1+
using System;
2+
using System.Data;
23
using System.Text;
4+
using ServiceStack.DataAnnotations;
35
using ServiceStack.Text;
46

57
namespace ServiceStack.OrmLite.SqlServer
@@ -42,14 +44,126 @@ public override string ToSelectStatement(ModelDefinition modelDef,
4244
return StringBuilderCache.ReturnAndFree(sb);
4345
}
4446

45-
public override void AppendFieldCondition(StringBuilder sqlFilter, FieldDefinition fieldDef, IDbCommand cmd)
47+
public override string GetColumnDefinition(FieldDefinition fieldDef)
4648
{
47-
if (!isSpatialField(fieldDef))
49+
// https://msdn.microsoft.com/en-us/library/ms182776.aspx
50+
if (fieldDef.IsRowVersion)
51+
return $"{fieldDef.FieldName} rowversion NOT NULL";
52+
53+
var fieldDefinition = fieldDef.CustomFieldDefinition ??
54+
GetColumnTypeDefinition(fieldDef.ColumnType, fieldDef.FieldLength, fieldDef.Scale);
55+
56+
var sql = StringBuilderCache.Allocate();
57+
sql.Append($"{GetQuotedColumnName(fieldDef.FieldName)} {fieldDefinition}");
58+
59+
if (fieldDef.IsPrimaryKey)
4860
{
49-
base.AppendFieldCondition(sqlFilter, fieldDef, cmd);
61+
sql.Append(" PRIMARY KEY");
62+
if (fieldDef.AutoIncrement)
63+
{
64+
sql.Append(" ").Append(AutoIncrementDefinition);
65+
}
5066
}
51-
else
67+
else
68+
{
69+
sql.Append(fieldDef.IsNullable ? " NULL" : " NOT NULL");
70+
}
71+
72+
// https://msdn.microsoft.com/en-us/library/ms184391.aspx
73+
var collation = fieldDef.PropertyInfo.FirstAttribute<SqlServerCollateAttribute>()?.Collation;
74+
if (!string.IsNullOrEmpty(collation))
75+
{
76+
sql.Append($" COLLATE {collation}");
77+
}
78+
79+
var defaultValue = GetDefaultValue(fieldDef);
80+
if (!string.IsNullOrEmpty(defaultValue))
81+
{
82+
sql.AppendFormat(DefaultValueFormat, defaultValue);
83+
}
84+
85+
return StringBuilderCache.ReturnAndFree(sql);
86+
}
87+
88+
public override string ToCreateTableStatement(Type tableType)
89+
{
90+
var sbColumns = StringBuilderCache.Allocate();
91+
var sbConstraints = StringBuilderCacheAlt.Allocate();
92+
var sbTableOptions = StringBuilderCacheAlt.Allocate();
93+
94+
var fileTableAttrib = tableType.FirstAttribute<SqlServerFileTableAttribute>();
95+
96+
var modelDef = GetModel(tableType);
97+
98+
if (fileTableAttrib == null)
99+
{
100+
foreach (var fieldDef in modelDef.FieldDefinitions)
101+
{
102+
if (fieldDef.CustomSelect != null)
103+
continue;
104+
105+
var columnDefinition = GetColumnDefinition(fieldDef);
106+
107+
if (columnDefinition == null)
108+
continue;
109+
110+
if (sbColumns.Length != 0)
111+
sbColumns.Append(", \n ");
112+
113+
sbColumns.Append(columnDefinition);
114+
115+
if (fieldDef.ForeignKey == null || OrmLiteConfig.SkipForeignKeys)
116+
continue;
117+
118+
var refModelDef = GetModel(fieldDef.ForeignKey.ReferenceType);
119+
sbConstraints.Append(
120+
$", \n\n CONSTRAINT {GetQuotedName(fieldDef.ForeignKey.GetForeignKeyName(modelDef, refModelDef, NamingStrategy, fieldDef))} " +
121+
$"FOREIGN KEY ({GetQuotedColumnName(fieldDef.FieldName)}) " +
122+
$"REFERENCES {GetQuotedTableName(refModelDef)} ({GetQuotedColumnName(refModelDef.PrimaryKey.FieldName)})");
123+
124+
sbConstraints.Append(GetForeignKeyOnDeleteClause(fieldDef.ForeignKey));
125+
sbConstraints.Append(GetForeignKeyOnUpdateClause(fieldDef.ForeignKey));
126+
}
127+
}
128+
else
52129
{
130+
if (fileTableAttrib.FileTableDirectory != null || fileTableAttrib.FileTableCollateFileName != null)
131+
{
132+
sbTableOptions.Append(" WITH (");
133+
134+
if (fileTableAttrib.FileTableDirectory != null)
135+
{
136+
sbTableOptions.Append($" FILETABLE_DIRECTORY = N'{fileTableAttrib.FileTableDirectory}'\n");
137+
}
138+
139+
if (fileTableAttrib.FileTableCollateFileName != null)
140+
{
141+
if (fileTableAttrib.FileTableDirectory != null)
142+
sbTableOptions.Append(" ,");
143+
144+
sbTableOptions.Append($" FILETABLE_COLLATE_FILENAME = {fileTableAttrib.FileTableCollateFileName ?? "database_default" }\n");
145+
}
146+
sbTableOptions.Append(")");
147+
}
148+
}
149+
150+
var sql = $"CREATE TABLE {GetQuotedTableName(modelDef)} ";
151+
sql += (fileTableAttrib != null)
152+
? $"\n AS FILETABLE{StringBuilderCache.ReturnAndFree(sbTableOptions)};"
153+
: $"\n(\n {StringBuilderCache.ReturnAndFree(sbColumns)}{StringBuilderCacheAlt.ReturnAndFree(sbConstraints)} \n){StringBuilderCache.ReturnAndFree(sbTableOptions)}; \n";
154+
155+
return sql;
156+
}
157+
158+
public override void AppendFieldCondition(StringBuilder sqlFilter, FieldDefinition fieldDef, IDbCommand cmd)
159+
{
160+
if (isSpatialField(fieldDef))
161+
{
162+
// Append condition statement to determine if SqlGeometry or SqlGeography type is Equal
163+
// using the type's STEquals method
164+
//
165+
// SqlGeometry: https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlgeometry.stequals.aspx
166+
// SqlGeography: https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlgeography.stequals.aspx
53167
sqlFilter
54168
.Append(GetQuotedColumnName(fieldDef.FieldName))
55169
.Append(".STEquals(")
@@ -58,23 +172,57 @@ public override void AppendFieldCondition(StringBuilder sqlFilter, FieldDefiniti
58172

59173
AddParameter(cmd, fieldDef);
60174
}
175+
else
176+
{
177+
base.AppendFieldCondition(sqlFilter, fieldDef, cmd);
178+
}
61179
}
62180

63181
public override void AppendNullFieldCondition(StringBuilder sqlFilter, FieldDefinition fieldDef)
64182
{
65-
if (!isSpatialField(fieldDef))
66-
{
67-
base.AppendNullFieldCondition(sqlFilter, fieldDef);
68-
}
69-
else
183+
if (hasIsNullProperty(fieldDef))
70184
{
185+
// Append condition statement to determine if SqlHierarchyId, SqlGeometry, or SqlGeography type is NULL
186+
// using the type's IsNull property
187+
//
188+
// SqlHierarchyId: https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlhierarchyid.isnull.aspx
189+
// SqlGeometry: https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlgeometry.isnull.aspx
190+
// SqlGeography: https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlgeography.isnull.aspx
71191
sqlFilter
72192
.Append(GetQuotedColumnName(fieldDef.FieldName))
73193
.Append(".IsNull = 1");
74194
}
195+
else
196+
{
197+
base.AppendNullFieldCondition(sqlFilter, fieldDef);
198+
}
75199
}
76200

77-
private bool isSpatialField(FieldDefinition fieldDef) =>
201+
internal bool isSpatialField(FieldDefinition fieldDef) =>
78202
fieldDef.FieldType.Name == "SqlGeography" || fieldDef.FieldType.Name == "SqlGeometry";
203+
204+
internal bool hasIsNullProperty(FieldDefinition fieldDef) =>
205+
isSpatialField(fieldDef) || fieldDef.FieldType.Name == "SqlHierarchyId";
206+
}
207+
}
208+
209+
210+
// TODO: Move to ServiceStack.Interfaces
211+
namespace ServiceStack.DataAnnotations
212+
{
213+
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
214+
public class SqlServerFileTableAttribute : AttributeBase
215+
{
216+
public SqlServerFileTableAttribute() { }
217+
218+
public SqlServerFileTableAttribute(string directory, string collateFileName = null)
219+
{
220+
FileTableDirectory = directory;
221+
FileTableCollateFileName = collateFileName;
222+
}
223+
224+
public string FileTableDirectory { get; internal set; }
225+
226+
public string FileTableCollateFileName { get; internal set; }
79227
}
80228
}

0 commit comments

Comments
 (0)