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,126 @@ 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 . IsPrimaryKey )
48
60
{
49
- base . AppendFieldCondition ( sqlFilter , fieldDef , cmd ) ;
61
+ sql . Append ( " PRIMARY KEY" ) ;
62
+ if ( fieldDef . AutoIncrement )
63
+ {
64
+ sql . Append ( " " ) . Append ( AutoIncrementDefinition ) ;
65
+ }
50
66
}
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
52
129
{
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
53
167
sqlFilter
54
168
. Append ( GetQuotedColumnName ( fieldDef . FieldName ) )
55
169
. Append ( ".STEquals(" )
@@ -58,23 +172,57 @@ public override void AppendFieldCondition(StringBuilder sqlFilter, FieldDefiniti
58
172
59
173
AddParameter ( cmd , fieldDef ) ;
60
174
}
175
+ else
176
+ {
177
+ base . AppendFieldCondition ( sqlFilter , fieldDef , cmd ) ;
178
+ }
61
179
}
62
180
63
181
public override void AppendNullFieldCondition ( StringBuilder sqlFilter , FieldDefinition fieldDef )
64
182
{
65
- if ( ! isSpatialField ( fieldDef ) )
66
- {
67
- base . AppendNullFieldCondition ( sqlFilter , fieldDef ) ;
68
- }
69
- else
183
+ if ( hasIsNullProperty ( fieldDef ) )
70
184
{
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
71
191
sqlFilter
72
192
. Append ( GetQuotedColumnName ( fieldDef . FieldName ) )
73
193
. Append ( ".IsNull = 1" ) ;
74
194
}
195
+ else
196
+ {
197
+ base . AppendNullFieldCondition ( sqlFilter , fieldDef ) ;
198
+ }
75
199
}
76
200
77
- private bool isSpatialField ( FieldDefinition fieldDef ) =>
201
+ internal bool isSpatialField ( FieldDefinition fieldDef ) =>
78
202
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 ; }
79
227
}
80
228
}
0 commit comments