From abb841b34d4c54821535a34a96079d396964041e Mon Sep 17 00:00:00 2001 From: Justin Darmody Date: Wed, 9 Jan 2013 15:18:33 +1100 Subject: [PATCH] Monotouch device fixes Numerous changes needed to overcome Monotouch limitations when deploying to devices. --- src/Catnap/Mapping/Impl/BasePropertyMap.cs | 13 +++++--- src/Catnap/Mapping/Impl/DomainMap.cs | 31 +++++++++++++------ .../Mapping/Impl/PropertyWithColumnMap.cs | 2 +- src/Catnap/Session.cs | 17 ++++++++-- 4 files changed, 46 insertions(+), 17 deletions(-) diff --git a/src/Catnap/Mapping/Impl/BasePropertyMap.cs b/src/Catnap/Mapping/Impl/BasePropertyMap.cs index 48b8e38..c134149 100644 --- a/src/Catnap/Mapping/Impl/BasePropertyMap.cs +++ b/src/Catnap/Mapping/Impl/BasePropertyMap.cs @@ -17,12 +17,16 @@ public abstract class BasePropertyMap : IProperty protected BasePropertyMap(string propertyName) { PropertyName = propertyName; + // -- Added by RD for Monotouch AOT compiler limitations + accessStrategy = new PropertyAccessStrategy(propertyName); } protected BasePropertyMap(Expression> property) { this.property = property; PropertyName = property.GetMemberExpression().Member.Name; + // -- Added by RD for Monotouch AOT compiler limitations + accessStrategy = new PropertyAccessStrategy(property); } public string PropertyName { get; private set; } @@ -69,10 +73,11 @@ public PropertyInfo PropertyInfo public virtual void Done(IDomainMap domainMap) { - access = access ?? DefaultAccess; - accessStrategy = property == null - ? access.CreateFor(PropertyName) - : access.CreateFor(property); + // -- Removed by RD due to Monotouch AOT compiler limitations, moved to constructor where type information is known. + //access = access ?? DefaultAccess; + //accessStrategy = property == null + // ? access.CreateFor(PropertyName) + // : access.CreateFor(property); } protected virtual IAccessStrategyFactory DefaultAccess diff --git a/src/Catnap/Mapping/Impl/DomainMap.cs b/src/Catnap/Mapping/Impl/DomainMap.cs index 1e1aa4d..d5a5f95 100644 --- a/src/Catnap/Mapping/Impl/DomainMap.cs +++ b/src/Catnap/Mapping/Impl/DomainMap.cs @@ -10,8 +10,10 @@ namespace Catnap.Mapping.Impl { public class DomainMap : IDomainMap, IDomainMappable { - private readonly IDbAdapter dbAdapter; - private readonly IDictionary entityMaps = new Dictionary(); + private IDbAdapter dbAdapter; + // -- Changed by RD to overcome Monotouch limitations when Value types are used as Dictionary Keys + // -- see http://docs.xamarin.com/ios/guides/advanced_topics/limitations + private Dictionary entityMaps = new Dictionary(); // - RD public DomainMap(IDbAdapter dbAdapter) { @@ -25,12 +27,12 @@ public DomainMap(IDbAdapter dbAdapter) public IEntityMappable Entity(Action> propertyMappings) where T : class, new() { - if (entityMaps.ContainsKey(typeof(T))) + if (entityMaps.ContainsKey(typeof(T).Name)) // RD - change { throw new ApplicationException(string.Format("Cannot map type '{0}' because it is already mapped.", typeof(T))); } var map = new EntityMap(propertyMappings); - entityMaps.Add(typeof(T), map); + entityMaps.Add(typeof(T).Name, map); return map; } @@ -58,23 +60,32 @@ public void ListParentIdColumnNameConvention(Func GetMapFor() where T : class, new() { - return (IEntityMap)entityMaps.First(x => x.Key == typeof(T)).Value; + return (IEntityMap)entityMaps.First(x => x.Key == typeof(T).Name).Value; // RD - change } public IEntityMap GetMapFor(Type type) { - return entityMaps.First(x => x.Key == type).Value; + return entityMaps.First(x => x.Key == type.Name).Value; // RD - change } - public void Done() + // -- RD wrapped done calls with exception handling - probably not needed. + public void Done () { - if (IdMappingConvention == null) + if (IdMappingConvention == null) { - IdMappingConvention = new IdMappingConvention(); + IdMappingConvention = new IdMappingConvention (); } foreach (var map in entityMaps.Values) { - map.Done(this, dbAdapter); + try + { + map.Done(this, dbAdapter); + } + catch (Exception e) + { + Console.WriteLine("FAILED Done for " + map.TableName + " " + e); + } + } } } diff --git a/src/Catnap/Mapping/Impl/PropertyWithColumnMap.cs b/src/Catnap/Mapping/Impl/PropertyWithColumnMap.cs index 2a325a8..d618a25 100644 --- a/src/Catnap/Mapping/Impl/PropertyWithColumnMap.cs +++ b/src/Catnap/Mapping/Impl/PropertyWithColumnMap.cs @@ -32,7 +32,7 @@ public TConcrete Column(string value) public override void Done(IDomainMap domainMap) { - base.Done(domainMap); + //base.Done(domainMap); RD removed call. ColumnName = ColumnName ?? GetDeafultColumnName(domainMap); } diff --git a/src/Catnap/Session.cs b/src/Catnap/Session.cs index e511a12..2eec3f2 100644 --- a/src/Catnap/Session.cs +++ b/src/Catnap/Session.cs @@ -42,7 +42,9 @@ public IList> List(IDbCommandSpec commandSpec) { commandSpec.GuardArgumentNull("commandSpec"); var command = commandFactory.Create(commandSpec.Parameters, commandSpec.CommandText); - return Try(() => ExecuteQuery(command)); + var result = Try(() => ExecuteQuery(command)); + command.Dispose (); //RD see http://www.aaronheise.com/2012/12/monotouch-sqlite-sigsegv/ + return result; } public IList List(IDbCommandSpec commandSpec) where T : class, new() @@ -60,6 +62,7 @@ public IList> List(IDbCommandSpec commandSpec) var command = entityMap.GetListCommand(predicateSpec.Parameters, predicateSpec.CommandText, commandFactory); var results = ExecuteQuery(command).Select(x => entityMap.BuildFrom(x, this)).ToList(); StoreAll(entityMap, results); + command.Dispose (); //RD see http://www.aaronheise.com/2012/12/monotouch-sqlite-sigsegv/ return results; } @@ -75,6 +78,7 @@ public IList> List(IDbCommandSpec commandSpec) var command = entityMap.GetListAllCommand(commandFactory); var results = ExecuteQuery(command).Select(x => entityMap.BuildFrom(x, this)).ToList(); StoreAll(entityMap, results); + command.Dispose(); //RD see http://www.aaronheise.com/2012/12/monotouch-sqlite-sigsegv/ return results; } @@ -90,6 +94,7 @@ public IList> List(IDbCommandSpec commandSpec) var command = entityMap.GetGetCommand(id, commandFactory); var result = ExecuteQuery(command).Select(x => entityMap.BuildFrom(x, this)).FirstOrDefault(); sessionCache.Store(id, result); + command.Dispose (); //RD see http://www.aaronheise.com/2012/12/monotouch-sqlite-sigsegv/ return result; } @@ -113,6 +118,7 @@ public IList> List(IDbCommandSpec commandSpec) } sessionCache.Store(entityMap.GetId(entity), entity); Cascade(entityMap, entity); + command.Dispose(); //RD see http://www.aaronheise.com/2012/12/monotouch-sqlite-sigsegv/ } private void Cascade(IEntityMap entityMap, T entity) where T : class, new() @@ -131,6 +137,7 @@ public IList> List(IDbCommandSpec commandSpec) var deleteCommand = map.GetDeleteCommand(id, commandFactory); Try(deleteCommand.ExecuteNonQuery); sessionCache.Store(id, null); + deleteCommand.Dispose (); //RD see http://www.aaronheise.com/2012/12/monotouch-sqlite-sigsegv/ } public void ExecuteNonQuery(IDbCommandSpec commandSpec) @@ -139,6 +146,7 @@ public void ExecuteNonQuery(IDbCommandSpec commandSpec) commandSpec.GuardArgumentNull("commandSpec"); var command = commandFactory.Create(commandSpec); Try(command.ExecuteNonQuery); + command.Dispose (); //RD } public IList> ExecuteQuery(IDbCommand command) @@ -158,6 +166,7 @@ public IList> ExecuteQuery(IDbCommand command) result.Add(row); } reader.Close(); + command.Dispose (); //RD see http://www.aaronheise.com/2012/12/monotouch-sqlite-sigsegv/ return result; } } @@ -167,7 +176,9 @@ public object ExecuteScalar(IDbCommandSpec commandSpec) GuardNotDisposed(); commandSpec.GuardArgumentNull("commandSpec"); var command = commandFactory.Create(commandSpec); - return Try(command.ExecuteScalar); + object result = Try(command.ExecuteScalar); + command.Dispose(); //RD see http://www.aaronheise.com/2012/12/monotouch-sqlite-sigsegv/ + return result; } public T ExecuteScalar(IDbCommandSpec commandSpec) @@ -176,6 +187,7 @@ public T ExecuteScalar(IDbCommandSpec commandSpec) commandSpec.GuardArgumentNull("commandSpec"); var command = commandFactory.Create(commandSpec); var result = Try(command.ExecuteScalar); + command.Dispose (); //RD see http://www.aaronheise.com/2012/12/monotouch-sqlite-sigsegv/ return (T)result; } @@ -183,6 +195,7 @@ public bool TableExists(string tableName) { var getTableMetadataCommand = DbAdapter.CreateGetTableMetadataCommand(tableName, commandFactory); var result = ExecuteQuery(getTableMetadataCommand); + getTableMetadataCommand.Dispose (); //RD see http://www.aaronheise.com/2012/12/monotouch-sqlite-sigsegv/ return result.Count > 0; }