| | 1 | | // Copyright (c) Microsoft Corporation. All rights reserved. |
| | 2 | | // Licensed under the MIT License. |
| | 3 | |
|
| | 4 | | using System; |
| | 5 | | using System.Collections; |
| | 6 | | using System.Collections.Generic; |
| | 7 | | using System.Globalization; |
| | 8 | | using Azure.Core; |
| | 9 | |
|
| | 10 | | namespace Azure.Data.Tables |
| | 11 | | { |
| | 12 | | /// <summary> |
| | 13 | | /// A <see cref="ITableEntity"/> type which allows callers direct access to the property map of the entity. |
| | 14 | | /// </summary> |
| | 15 | | public partial class TableEntity : ITableEntity |
| | 16 | | { |
| | 17 | | private readonly IDictionary<string, object> _properties; |
| | 18 | |
|
| | 19 | | /// <summary> |
| | 20 | | /// The partition key is a unique identifier for the partition within a given table and forms the first part of |
| | 21 | | /// </summary> |
| | 22 | | /// <value>A string containing the partition key for the entity.</value> |
| | 23 | | public string PartitionKey |
| | 24 | | { |
| 1028 | 25 | | get { return GetString(TableConstants.PropertyNames.PartitionKey); } |
| 32 | 26 | | set { _properties[TableConstants.PropertyNames.PartitionKey] = value; } |
| | 27 | | } |
| | 28 | |
|
| | 29 | | /// <summary> |
| | 30 | | /// The row key is a unique identifier for an entity within a given partition. Together the <see cref="Partition |
| | 31 | | /// </summary> |
| | 32 | | /// <value>A string containing the row key for the entity.</value> |
| | 33 | | public string RowKey |
| | 34 | | { |
| 1020 | 35 | | get { return GetString(TableConstants.PropertyNames.RowKey); } |
| 32 | 36 | | set { _properties[TableConstants.PropertyNames.RowKey] = value; } |
| | 37 | | } |
| | 38 | |
|
| | 39 | | /// <summary> |
| | 40 | | /// The Timestamp property is a DateTime value that is maintained on the server side to record the time an entit |
| | 41 | | /// The Table service uses the Timestamp property internally to provide optimistic concurrency. The value of Tim |
| | 42 | | /// meaning that each time the entity is modified, the value of Timestamp increases for that entity. This proper |
| | 43 | | /// </summary> |
| | 44 | | /// <value>A <see cref="DateTimeOffset"/> containing the timestamp of the entity.</value> |
| | 45 | | public DateTimeOffset? Timestamp |
| | 46 | | { |
| 2 | 47 | | get { return GetValue(TableConstants.PropertyNames.TimeStamp) as DateTimeOffset?; } |
| 0 | 48 | | set { _properties[TableConstants.PropertyNames.TimeStamp] = value; } |
| | 49 | | } |
| | 50 | |
|
| | 51 | | /// <summary> |
| | 52 | | /// Gets or sets the entity's ETag. Set this value to '*' in order to force an overwrite to an entity as part of |
| | 53 | | /// </summary> |
| | 54 | | /// <value>A string containing the ETag value for the entity.</value> |
| | 55 | | public string ETag |
| | 56 | | { |
| 80 | 57 | | get { return GetString(TableConstants.PropertyNames.Etag); } |
| 0 | 58 | | set { _properties[TableConstants.PropertyNames.Etag] = value; } |
| | 59 | | } |
| | 60 | |
|
| | 61 | | /// <summary> |
| | 62 | | /// Constructs an instance of a <see cref="ITableEntity" />. |
| | 63 | | /// </summary> |
| | 64 | | public TableEntity() |
| 2350 | 65 | | : this(null) |
| | 66 | | { |
| 2350 | 67 | | } |
| | 68 | |
|
| | 69 | | /// <summary> |
| | 70 | | /// Initializes a new instance of the <see cref="TableEntity"/> class with the specified partition key and row k |
| | 71 | | /// </summary> |
| | 72 | | /// <param name="partitionKey">A string containing the partition key of the <see cref="TableEntity"/> to be init |
| | 73 | | /// <param name="rowKey">A string containing the row key of the <see cref="TableEntity"/> to be initialized.</pa |
| | 74 | | public TableEntity(string partitionKey, string rowKey) |
| 8 | 75 | | : this(null) |
| | 76 | | { |
| 8 | 77 | | PartitionKey = partitionKey; |
| 8 | 78 | | RowKey = rowKey; |
| 8 | 79 | | } |
| | 80 | |
|
| | 81 | | /// <summary> |
| | 82 | | /// Initializes a new instance of the <see cref="TableEntity"/> class with properties in the <see cref="IDiction |
| | 83 | | /// </summary> |
| | 84 | | /// <param name="values">A <see cref="IDictionary"/> containing the initial values of the entity.</param> |
| 2518 | 85 | | public TableEntity(IDictionary<string, object> values) |
| | 86 | | { |
| 2518 | 87 | | _properties = values != null ? |
| 2518 | 88 | | new Dictionary<string, object>(values) : |
| 2518 | 89 | | new Dictionary<string, object>(); |
| 2518 | 90 | | } |
| | 91 | |
|
| | 92 | | /// <summary> |
| | 93 | | /// Get the value of a <see cref="TableEntity"/>'s |
| | 94 | | /// <see cref="String"/> property called |
| | 95 | | /// <paramref name="key"/>. |
| | 96 | | /// </summary> |
| | 97 | | /// <param name="key">The name of the property.</param> |
| | 98 | | /// <returns>The value of the property.</returns> |
| | 99 | | /// <exception cref="InvalidOperationException">Value associated with given <paramref name="key"/> is not of typ |
| 2136 | 100 | | public string GetString(string key) => GetValue<string>(key); |
| | 101 | |
|
| | 102 | | /// <summary> |
| | 103 | | /// Get the value of a <see cref="TableEntity"/>'s |
| | 104 | | /// <see cref="byte"/> property called |
| | 105 | | /// <paramref name="key"/>. |
| | 106 | | /// </summary> |
| | 107 | | /// <param name="key">The name of the property.</param> |
| | 108 | | /// <returns>The value of the property.</returns> |
| | 109 | | /// <exception cref="InvalidOperationException">Value associated with given <paramref name="key"/> is not of typ |
| 8 | 110 | | public byte[] GetBinary(string key) => GetValue<byte[]>(key); |
| | 111 | |
|
| | 112 | | /// <summary> |
| | 113 | | /// Get the value of a <see cref="TableEntity"/>'s |
| | 114 | | /// <see cref="String"/> property called |
| | 115 | | /// <paramref name="key"/>. |
| | 116 | | /// </summary> |
| | 117 | | /// <param name="key">The name of the property.</param> |
| | 118 | | /// <returns>The value of the property.</returns> |
| | 119 | | /// <exception cref="InvalidOperationException">Value associated with given <paramref name="key"/> is not of typ |
| 10 | 120 | | public bool? GetBoolean(string key) => GetValue<bool?>(key); |
| | 121 | |
|
| | 122 | | /// <summary> |
| | 123 | | /// Get the value of a <see cref="TableEntity"/>'s |
| | 124 | | /// <see cref="DateTime"/> property called |
| | 125 | | /// <paramref name="key"/>. |
| | 126 | | /// </summary> |
| | 127 | | /// <param name="key">The name of the property.</param> |
| | 128 | | /// <returns>The value of the property.</returns> |
| | 129 | | /// <exception cref="InvalidOperationException">Value associated with given <paramref name="key"/> is not of typ |
| 8 | 130 | | public DateTime? GetDateTime(string key) => GetValue<DateTime?>(key); |
| | 131 | |
|
| | 132 | | /// <summary> |
| | 133 | | /// Get the value of a <see cref="TableEntity"/>'s |
| | 134 | | /// <see cref="Double"/> property called |
| | 135 | | /// <paramref name="key"/>. |
| | 136 | | /// </summary> |
| | 137 | | /// <param name="key">The name of the property.</param> |
| | 138 | | /// <returns>The value of the property.</returns> |
| | 139 | | /// <exception cref="InvalidOperationException">Value associated with given <paramref name="key"/> is not of typ |
| 8 | 140 | | public double? GetDouble(string key) => GetValue<double?>(key); |
| | 141 | |
|
| | 142 | | /// <summary> |
| | 143 | | /// Get the value of a <see cref="TableEntity"/>'s |
| | 144 | | /// <see cref="Guid"/> property called |
| | 145 | | /// <paramref name="key"/>. |
| | 146 | | /// </summary> |
| | 147 | | /// <param name="key">The name of the property.</param> |
| | 148 | | /// <returns>The value of the property.</returns> |
| | 149 | | /// <exception cref="InvalidOperationException">Value associated with given <paramref name="key"/> is not of typ |
| 8 | 150 | | public Guid? GetGuid(string key) => GetValue<Guid?>(key); |
| | 151 | |
|
| | 152 | | /// <summary> |
| | 153 | | /// Get the value of a <see cref="TableEntity"/>'s |
| | 154 | | /// <see cref="Int32"/> property called |
| | 155 | | /// <paramref name="key"/>. |
| | 156 | | /// </summary> |
| | 157 | | /// <param name="key">The name of the property.</param> |
| | 158 | | /// <returns>The value of the property.</returns> |
| | 159 | | /// <exception cref="InvalidOperationException">Value associated with given <paramref name="key"/> is not of typ |
| 8 | 160 | | public int? GetInt32(string key) => GetValue<int?>(key); |
| | 161 | |
|
| | 162 | | /// <summary> |
| | 163 | | /// Get the value of a <see cref="TableEntity"/>'s |
| | 164 | | /// <see cref="Int64"/> property called |
| | 165 | | /// <paramref name="key"/>. |
| | 166 | | /// </summary> |
| | 167 | | /// <param name="key">The name of the property.</param> |
| | 168 | | /// <returns>The value of the property.</returns> |
| | 169 | | /// <exception cref="InvalidOperationException">Value associated with given <paramref name="key"/> is not of typ |
| 8 | 170 | | public long? GetInt64(string key) => GetValue<long?>(key); |
| | 171 | |
|
| | 172 | | /// <summary> |
| | 173 | | /// Set a document property. |
| | 174 | | /// </summary> |
| | 175 | | /// <param name="key">The property name.</param> |
| | 176 | | /// <param name="value">The property value.</param> |
| | 177 | | /// <exception cref="InvalidOperationException">The given <paramref name="value"/> does not match the type of th |
| | 178 | | private protected void SetValue(string key, object value) |
| | 179 | | { |
| 33154 | 180 | | Argument.AssertNotNullOrEmpty(key, nameof(key)); |
| | 181 | |
|
| 33154 | 182 | | if (value != null && _properties.TryGetValue(key, out object existingValue) && existingValue != null) |
| | 183 | | { |
| 52 | 184 | | EnforceType(existingValue.GetType(), value.GetType()); |
| | 185 | | } |
| 33152 | 186 | | _properties[key] = value; |
| 33152 | 187 | | } |
| | 188 | |
|
| | 189 | | /// <summary> |
| | 190 | | /// Get an entity property. |
| | 191 | | /// </summary> |
| | 192 | | /// <typeparam name="T">The expected type of the property value.</typeparam> |
| | 193 | | /// <param name="key">The property name.</param> |
| | 194 | | /// <returns>The value of the property.</returns> |
| | 195 | | /// <exception cref="InvalidOperationException">Value associated with given <paramref name="key"/> is not of giv |
| 2194 | 196 | | private protected T GetValue<T>(string key) => (T)GetValue(key, typeof(T)); |
| | 197 | |
|
| | 198 | | /// <summary> |
| | 199 | | /// Get an entity property. |
| | 200 | | /// </summary> |
| | 201 | | /// <param name="key">The property name.</param> |
| | 202 | | /// <param name="type">The expected type of the property value.</param> |
| | 203 | | /// <returns>The value of the property.</returns> |
| | 204 | | /// <exception cref="InvalidOperationException">Value associated with given <paramref name="key"/> is not of typ |
| | 205 | | private protected object GetValue(string key, Type type = null) |
| | 206 | | { |
| 2436 | 207 | | Argument.AssertNotNullOrEmpty(key, nameof(key)); |
| 2436 | 208 | | if (!_properties.TryGetValue(key, out object value) || value == null) |
| | 209 | | { |
| 56 | 210 | | return null; |
| | 211 | | } |
| | 212 | |
|
| 2380 | 213 | | if (type != null) |
| | 214 | | { |
| 2146 | 215 | | EnforceType(type, value.GetType()); |
| | 216 | | } |
| | 217 | |
|
| 2364 | 218 | | return value; |
| | 219 | | } |
| | 220 | |
|
| | 221 | | /// <summary> |
| | 222 | | /// Ensures that the given type matches the type of the existing |
| | 223 | | /// property; throws an exception if the types do not match. |
| | 224 | | /// </summary> |
| | 225 | | private static void EnforceType(Type requestedType, Type givenType) |
| | 226 | | { |
| 2198 | 227 | | if (!requestedType.IsAssignableFrom(givenType)) |
| | 228 | | { |
| 18 | 229 | | throw new InvalidOperationException(string.Format( |
| 18 | 230 | | CultureInfo.InvariantCulture, |
| 18 | 231 | | $"Cannot return {requestedType} type for a {givenType} typed property.")); |
| | 232 | | } |
| 2180 | 233 | | } |
| | 234 | | } |
| | 235 | | } |