-
Notifications
You must be signed in to change notification settings - Fork 600
/
ColumnInfo.cs
153 lines (139 loc) · 7.73 KB
/
ColumnInfo.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
using System;
using System.Linq;
using System.Reflection;
namespace PetaPoco
{
/// <summary>
/// The ColumnInfo class stores information about a column in the database.
/// </summary>
/// <remarks>
/// Typically ColumnInfo is automatically populated from the attributes on a POCO object and its properties. It can, however, also be
/// returned from the <see cref="IMapper"/> interface allowing you to provide your own custom bindings between the DB and your POCOs.
/// </remarks>
/// <seealso cref="ColumnAttribute"/>
/// <seealso cref="Core.PocoColumn"/>
public class ColumnInfo
{
/// <summary>
/// Gets or sets the database column name this property maps to.
/// </summary>
/// <value>When not <see langword="null"/>, overrides this property's inflected column name from the mapper.</value>
/// <seealso cref="ColumnAttribute.Name"/>
public string ColumnName { get; set; }
/// <summary>
/// Gets or sets whether this column represents a property that should be updated in queries that include a user-supplied
/// <c>SELECT</c> statement, but ignored in queries generated by auto-select. Result columns are always ignored in <c>UPDATE</c> and
/// <c>INSERT</c> operations.
/// </summary>
/// <value>If <see langword="true"/>, this property will be updated in SQL query operations containing a user-supplied <c>SELECT</c>
/// statement, and ignored for all other database operations.</value>
/// <seealso cref="ResultColumnAttribute"/>
public bool ResultColumn { get; set; }
/// <summary>
/// Gets or sets whether this serves as a ResultColumn that is included with auto-select queries as well as queries containing
/// user-supplied <c>SELECT</c> statements.
/// </summary>
/// <value>If <see langword="true"/>, this property will be updated in all SQL queries, but ignored for all other database
/// operations such as INSERT and UPDATE.</value>
/// <seealso cref="ResultColumnAttribute.IncludeInAutoSelect"/>
public bool AutoSelectedResultColumn { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the column's data type should be treated as <see cref="System.Data.DbType.AnsiString"/>.
/// </summary>
/// <remarks>
/// For use with <see cref="string"/> properties. This property is implicitly <see langword="true"/> for properties of type <see
/// cref="AnsiString"/>.
/// </remarks>
/// <value>If <see langword="true"/>, the column's data type is assumed to be <see
/// cref="System.Data.DbType.AnsiString">DbType.AnsiString</see> (equivalent to the DB data type <c>VARCHAR</c>).</value>
/// <seealso cref="AnsiString"/>
/// <seealso cref="ColumnAttribute.ForceToAnsiString"/>
public bool ForceToAnsiString { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the column containing a DateTime data type should be treated as <see
/// cref="System.Data.DbType.DateTime">DbType.DateTime</see>.
/// </summary>
/// <remarks>
/// For use with <see cref="DateTime"/> properties. This property is implicitly <see langword="true"/> for properties of type <see
/// cref="DateTime2"/>.
/// </remarks>
/// <value>If <see langword="true"/>, the column's data type is assumed to be <see
/// cref="System.Data.DbType.DateTime">DbType.DateTime</see>.</value>
/// <seealso cref="DateTime2"/>
/// <seealso cref="ColumnAttribute.ForceToDateTime2"/>
public bool ForceToDateTime2 { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the DateTime value of this column should be treated as UTC.
/// </summary>
/// <remarks>
/// For use with <see cref="DateTime"/> or <see cref="DateTime2"/> properties. No conversion is applied - the <see
/// cref="DateTimeKind"/> of the POCO property's underlying <see cref="DateTime"/> value is simply set to correctly reflect the UTC
/// timezone as an invariant.
/// </remarks>
/// <value>If <see langword="true"/>, the DateTime value is assumed to be in UTC. If <see langword="false"/>, the <see
/// cref="DateTime.Kind"/> property will be assigned <see cref="DateTimeKind.Unspecified"/>.</value>
/// <seealso cref="DateTime2"/>
/// <seealso cref="ColumnAttribute.ForceToUtc"/>
public bool ForceToUtc { get; set; }
/// <summary>
/// Gets or sets the template used for <c>INSERT</c> operations.
/// </summary>
/// <remarks>
/// When set, this template is used for generating the <c>INSERT</c> portion of the SQL statement instead of the default
/// <br/><c>String.Format("{0}{1}", paramPrefix, index)</c>.
/// <para>Setting this allows database-related interactions, such as:
/// <br/><c>String.Format("CAST({0}{1} AS JSON)", paramPrefix, index)</c>.</para>
/// </remarks>
/// <seealso cref="ColumnAttribute.InsertTemplate"/>
public string InsertTemplate { get; set; }
/// <summary>
/// Gets or sets the template used for <c>UPDATE</c> operations.
/// </summary>
/// <remarks>
/// When set, this template is used for generating the <c>UPDATE</c> portion of the SQL statement instead of the default
/// <br/><c>String.Format("{0} = {1}{2}", colName, paramPrefix, index)</c>.
/// <para>Setting this allows database-related interactions, such as:
/// <br/><c>String.Format("{0} = CAST({1}{2} AS JSON)", colName, paramPrefix, index)</c></para>
/// </remarks>
/// <seealso cref="ColumnAttribute.UpdateTemplate"/>
public string UpdateTemplate { get; set; }
/// <summary>
/// Creates and populates a ColumnInfo from the attributes of a POCO property.
/// </summary>
/// <param name="propertyInfo">The POCO property to use for initializing the ColumnInfo.</param>
/// <returns>A ColumnInfo instance.</returns>
public static ColumnInfo FromProperty(PropertyInfo propertyInfo)
{
var ci = new ColumnInfo();
PopulateFromProperty(propertyInfo, ref ci, out _);
return ci;
}
internal static void PopulateFromProperty(PropertyInfo pi, ref ColumnInfo ci, out ColumnAttribute columnAttr)
{
// Check if declaring poco has [Explicit] attribute
var isExplicit = pi.DeclaringType.GetCustomAttributes(typeof(ExplicitColumnsAttribute), true).Any();
// Check for [Column]/[Ignore] Attributes
columnAttr = Attribute.GetCustomAttributes(pi, typeof(ColumnAttribute)).FirstOrDefault() as ColumnAttribute;
var isIgnore = Attribute.GetCustomAttributes(pi, typeof(IgnoreAttribute)).Any();
if (isIgnore || (isExplicit && columnAttr == null))
{
ci = null;
}
else
{
ci = ci ?? new ColumnInfo();
ci.ColumnName = columnAttr?.Name ?? pi.Name;
ci.ForceToAnsiString = columnAttr?.ForceToAnsiString == true;
ci.ForceToDateTime2 = columnAttr?.ForceToDateTime2 == true;
ci.ForceToUtc = columnAttr?.ForceToUtc == true;
ci.InsertTemplate = columnAttr?.InsertTemplate;
ci.UpdateTemplate = columnAttr?.UpdateTemplate;
if (columnAttr is ResultColumnAttribute resAttr)
{
ci.ResultColumn = true;
ci.AutoSelectedResultColumn = resAttr.IncludeInAutoSelect == IncludeInAutoSelect.Yes;
}
}
}
}
}