Esempio n. 1
0
        /// <summary>
        /// Gets the name of the table.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        /// <exception cref="System.ApplicationException">Failed to resolve TableName for Type:  + type.FullName</exception>
        private static string GetTableName(Type type)
        {
            StringCacheData cacheData;

            if (_cachedTypeTableNames.TryGetValue(type.TypeHandle, out cacheData))
            {
                var expired = CacheExpirationTicks;
                if (cacheData.LastAccess < expired)
                {
                    // If expired, remove from cache
                    StringCacheData removed;
                    _cachedTypeTableNames.TryRemove(type.TypeHandle, out removed);
                }
                else
                {
                    // If not expired, update last access and return it
                    var updated = cacheData.Clone();
                    _cachedTypeTableNames.TryUpdate(type.TypeHandle, updated, cacheData);

                    return(updated.Data);
                }
            }

            // Default table name is class name
            var name = type.Name;

            // Remove interface prefix, if any
            if (type.IsInterface && name.StartsWith("I"))
            {
                name = name.Substring(1);
            }

            // Support decoration using TableAttribute
            // NOTE: This as dynamic trick should be able to handle both our own Table-attribute as well as the one in EntityFramework
            var tableattr = type.GetCustomAttributes(false).Where(attr => attr.GetType().Name == "TableAttribute").SingleOrDefault() as dynamic;

            if (tableattr != null)
            {
                name = tableattr.Name;
            }

            // Guard against null table name
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ApplicationException("Failed to resolve TableName for Type: " + type.FullName);
            }

            // Cache mapping
            cacheData = new StringCacheData(name);
            _cachedTypeTableNames.TryAdd(type.TypeHandle, cacheData);

            return(cacheData.Data);
        }
Esempio n. 2
0
        /// <summary>
        /// Returns a single entity by a single id from table "T".
        /// If T is an interface a proxy is generated.
        /// Id must be marked with [Key] attribute.
        /// Entity is tracked/intercepted for changes and used by the Update() extension.
        /// </summary>
        /// <typeparam name="T">Entity Type</typeparam>
        /// <param name="connection">Open SqlConnection</param>
        /// <param name="id">Id of the entity to get, must be marked with [Key] attribute</param>
        /// <returns>Entity of T</returns>
        public static T Get <T>(this IDbConnection connection, dynamic id, IDbTransaction transaction = null, int?commandTimeout = null) where T : class
        {
            // Argument Validation
            if (connection == null)
            {
                throw new ArgumentNullException("connection", "connection cannot be null");
            }
            if (id == null)
            {
                throw new ArgumentNullException("id", "id cannot be null");
            }

            InitializeCacheSweeper();

            var type = typeof(T);

            StringCacheData cacheData;

            // Retrieve cached query
            if (!_cachedQueries.TryGetValue(type.TypeHandle, out cacheData))
            {
                var keys = KeyPropertiesCache(type);
                if (keys.Count() > 1)
                {
                    throw new DataException("Get<T> only supports an entity with a single [Key] property");
                }
                if (keys.Count() == 0)
                {
                    throw new DataException("Get<T> only supports an entity with a [Key] property");
                }

                var onlyKey = keys.First();

                var name = GetTableName(type);

                // TODO: query information schema and only select fields that are both in information schema and underlying class / interface
                var sql = "select * from " + name + " where " + onlyKey.Name + " = @id";

                cacheData = new StringCacheData(sql);
                _cachedQueries.TryAdd(type.TypeHandle, cacheData);
            }

            // Build parameters
            var dynParms = new Dapper.DynamicParameters();

            dynParms.Add("@id", id);

            T obj = null;

            // Processing
            //if (type.IsInterface) // Create proxy if interface
            //{
            //    // Execute
            //    var res = connection.Query(cacheData.Data, dynParms).SingleOrDefault() as IDictionary<string, object>;
            //    if (res == null) return (T)((object)null);

            //    // Create proxy
            //    obj = ProxyGenerator.GetInterfaceProxy<T>();

            //    // Map properties
            //    foreach (var property in TypePropertiesCache(type))
            //    {
            //        var val = res[property.Name];
            //        property.SetValue(obj, val, null);
            //    }

            //    // Reset change tracking
            //    ((IProxy)obj).IsDirty = false;
            //}
            //else
            //{
            //obj = connection.Query<T>(cacheData.Data, dynParms, transaction: transaction, commandTimeout: commandTimeout).SingleOrDefault();
            //}

            ISqlAdapter adapter = GetFormatter(connection);

            obj = adapter.Get <T>(connection, transaction, commandTimeout, cacheData.Data, dynParms);

            return(obj);
        }