1
- using System . Data ;
1
+ using System ;
2
+ using System . Data ;
2
3
using System . Text ;
4
+ using ServiceStack . DataAnnotations ;
3
5
using ServiceStack . Text ;
4
6
5
7
namespace ServiceStack . OrmLite . SqlServer
@@ -42,14 +44,129 @@ public override string ToSelectStatement(ModelDefinition modelDef,
42
44
return StringBuilderCache . ReturnAndFree ( sb ) ;
43
45
}
44
46
45
- public override void AppendFieldCondition ( StringBuilder sqlFilter , FieldDefinition fieldDef , IDbCommand cmd )
47
+ public override string GetColumnDefinition ( FieldDefinition fieldDef )
46
48
{
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 . FieldType == typeof ( string ) )
48
60
{
49
- base . AppendFieldCondition ( sqlFilter , fieldDef , cmd ) ;
61
+ // https://msdn.microsoft.com/en-us/library/ms184391.aspx
62
+ var collation = fieldDef . PropertyInfo . FirstAttribute < SqlServerCollateAttribute > ( ) ? . Collation ;
63
+ if ( ! string . IsNullOrEmpty ( collation ) )
64
+ {
65
+ sql . Append ( $ " COLLATE { collation } ") ;
66
+ }
50
67
}
51
- else
68
+
69
+ if ( fieldDef . IsPrimaryKey )
70
+ {
71
+ sql . Append ( " PRIMARY KEY" ) ;
72
+ if ( fieldDef . AutoIncrement )
73
+ {
74
+ sql . Append ( " " ) . Append ( AutoIncrementDefinition ) ;
75
+ }
76
+ }
77
+ else
78
+ {
79
+ sql . Append ( fieldDef . IsNullable ? " NULL" : " NOT NULL" ) ;
80
+ }
81
+
82
+ var defaultValue = GetDefaultValue ( fieldDef ) ;
83
+ if ( ! string . IsNullOrEmpty ( defaultValue ) )
84
+ {
85
+ sql . AppendFormat ( DefaultValueFormat , defaultValue ) ;
86
+ }
87
+
88
+ return StringBuilderCache . ReturnAndFree ( sql ) ;
89
+ }
90
+
91
+ public override string ToCreateTableStatement ( Type tableType )
92
+ {
93
+ var sbColumns = StringBuilderCache . Allocate ( ) ;
94
+ var sbConstraints = StringBuilderCacheAlt . Allocate ( ) ;
95
+ var sbTableOptions = StringBuilderCacheAlt . Allocate ( ) ;
96
+
97
+ var fileTableAttrib = tableType . FirstAttribute < SqlServerFileTableAttribute > ( ) ;
98
+
99
+ var modelDef = GetModel ( tableType ) ;
100
+
101
+ if ( fileTableAttrib == null )
102
+ {
103
+ foreach ( var fieldDef in modelDef . FieldDefinitions )
104
+ {
105
+ if ( fieldDef . CustomSelect != null )
106
+ continue ;
107
+
108
+ var columnDefinition = GetColumnDefinition ( fieldDef ) ;
109
+
110
+ if ( columnDefinition == null )
111
+ continue ;
112
+
113
+ if ( sbColumns . Length != 0 )
114
+ sbColumns . Append ( ", \n " ) ;
115
+
116
+ sbColumns . Append ( columnDefinition ) ;
117
+
118
+ if ( fieldDef . ForeignKey == null || OrmLiteConfig . SkipForeignKeys )
119
+ continue ;
120
+
121
+ var refModelDef = GetModel ( fieldDef . ForeignKey . ReferenceType ) ;
122
+ sbConstraints . Append (
123
+ $ ", \n \n CONSTRAINT { GetQuotedName ( fieldDef . ForeignKey . GetForeignKeyName ( modelDef , refModelDef , NamingStrategy , fieldDef ) ) } " +
124
+ $ "FOREIGN KEY ({ GetQuotedColumnName ( fieldDef . FieldName ) } ) " +
125
+ $ "REFERENCES { GetQuotedTableName ( refModelDef ) } ({ GetQuotedColumnName ( refModelDef . PrimaryKey . FieldName ) } )") ;
126
+
127
+ sbConstraints . Append ( GetForeignKeyOnDeleteClause ( fieldDef . ForeignKey ) ) ;
128
+ sbConstraints . Append ( GetForeignKeyOnUpdateClause ( fieldDef . ForeignKey ) ) ;
129
+ }
130
+ }
131
+ else
52
132
{
133
+ if ( fileTableAttrib . FileTableDirectory != null || fileTableAttrib . FileTableCollateFileName != null )
134
+ {
135
+ sbTableOptions . Append ( " WITH (" ) ;
136
+
137
+ if ( fileTableAttrib . FileTableDirectory != null )
138
+ {
139
+ sbTableOptions . Append ( $ " FILETABLE_DIRECTORY = N'{ fileTableAttrib . FileTableDirectory } '\n ") ;
140
+ }
141
+
142
+ if ( fileTableAttrib . FileTableCollateFileName != null )
143
+ {
144
+ if ( fileTableAttrib . FileTableDirectory != null )
145
+ sbTableOptions . Append ( " ," ) ;
146
+
147
+ sbTableOptions . Append ( $ " FILETABLE_COLLATE_FILENAME = { fileTableAttrib . FileTableCollateFileName ?? "database_default" } \n ") ;
148
+ }
149
+ sbTableOptions . Append ( ")" ) ;
150
+ }
151
+ }
152
+
153
+ var sql = $ "CREATE TABLE { GetQuotedTableName ( modelDef ) } ";
154
+ sql += ( fileTableAttrib != null )
155
+ ? $ "\n AS FILETABLE{ StringBuilderCache . ReturnAndFree ( sbTableOptions ) } ;"
156
+ : $ "\n (\n { StringBuilderCache . ReturnAndFree ( sbColumns ) } { StringBuilderCacheAlt . ReturnAndFree ( sbConstraints ) } \n ){ StringBuilderCache . ReturnAndFree ( sbTableOptions ) } ; \n ";
157
+
158
+ return sql ;
159
+ }
160
+
161
+ public override void AppendFieldCondition ( StringBuilder sqlFilter , FieldDefinition fieldDef , IDbCommand cmd )
162
+ {
163
+ if ( isSpatialField ( fieldDef ) )
164
+ {
165
+ // Append condition statement to determine if SqlGeometry or SqlGeography type is Equal
166
+ // using the type's STEquals method
167
+ //
168
+ // SqlGeometry: https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlgeometry.stequals.aspx
169
+ // SqlGeography: https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlgeography.stequals.aspx
53
170
sqlFilter
54
171
. Append ( GetQuotedColumnName ( fieldDef . FieldName ) )
55
172
. Append ( ".STEquals(" )
@@ -58,23 +175,57 @@ public override void AppendFieldCondition(StringBuilder sqlFilter, FieldDefiniti
58
175
59
176
AddParameter ( cmd , fieldDef ) ;
60
177
}
178
+ else
179
+ {
180
+ base . AppendFieldCondition ( sqlFilter , fieldDef , cmd ) ;
181
+ }
61
182
}
62
183
63
184
public override void AppendNullFieldCondition ( StringBuilder sqlFilter , FieldDefinition fieldDef )
64
185
{
65
- if ( ! isSpatialField ( fieldDef ) )
66
- {
67
- base . AppendNullFieldCondition ( sqlFilter , fieldDef ) ;
68
- }
69
- else
186
+ if ( hasIsNullProperty ( fieldDef ) )
70
187
{
188
+ // Append condition statement to determine if SqlHierarchyId, SqlGeometry, or SqlGeography type is NULL
189
+ // using the type's IsNull property
190
+ //
191
+ // SqlHierarchyId: https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlhierarchyid.isnull.aspx
192
+ // SqlGeometry: https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlgeometry.isnull.aspx
193
+ // SqlGeography: https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlgeography.isnull.aspx
71
194
sqlFilter
72
195
. Append ( GetQuotedColumnName ( fieldDef . FieldName ) )
73
196
. Append ( ".IsNull = 1" ) ;
74
197
}
198
+ else
199
+ {
200
+ base . AppendNullFieldCondition ( sqlFilter , fieldDef ) ;
201
+ }
75
202
}
76
203
77
- private bool isSpatialField ( FieldDefinition fieldDef ) =>
204
+ internal bool isSpatialField ( FieldDefinition fieldDef ) =>
78
205
fieldDef . FieldType . Name == "SqlGeography" || fieldDef . FieldType . Name == "SqlGeometry" ;
206
+
207
+ internal bool hasIsNullProperty ( FieldDefinition fieldDef ) =>
208
+ isSpatialField ( fieldDef ) || fieldDef . FieldType . Name == "SqlHierarchyId" ;
209
+ }
210
+ }
211
+
212
+
213
+ // TODO: Move to ServiceStack.Interfaces
214
+ namespace ServiceStack . DataAnnotations
215
+ {
216
+ [ AttributeUsage ( AttributeTargets . Class , AllowMultiple = false , Inherited = true ) ]
217
+ public class SqlServerFileTableAttribute : AttributeBase
218
+ {
219
+ public SqlServerFileTableAttribute ( ) { }
220
+
221
+ public SqlServerFileTableAttribute ( string directory , string collateFileName = null )
222
+ {
223
+ FileTableDirectory = directory ;
224
+ FileTableCollateFileName = collateFileName ;
225
+ }
226
+
227
+ public string FileTableDirectory { get ; internal set ; }
228
+
229
+ public string FileTableCollateFileName { get ; internal set ; }
79
230
}
80
231
}
0 commit comments