Hi Jon, For ObjectFactory, you may proceed (I wrote it, and it was supposed to be temporary).
Regarding the fact of loading a given vendor, without referencing it, the following threads were talking about it: http://groups.google.com/group/dblinq/browse_thread/thread/9e3b0ffa5f2d7e1f/6716fb3496c10b5f http://groups.google.com/group/dblinq/browse_thread/thread/ce397e5f58b36a12/d7378bd1c401957a Pascal. jabber/gtalk: [email protected] msn: [email protected] On Mon, Mar 2, 2009 at 22:24, Jonathan Pryor <[email protected]> wrote: > While working on the database-independent tests, I ran across > ReflectonObjectFactory.Parse(), and wondered if there was a way to improve > this method. It currently contains: > > var assemblyTypes = assembly.GetTypes(); > foreach (Type type in assemblyTypes) > { > if (type.IsAbstract) > continue; > foreach (Type i in type.GetInterfaces()) > { > if (i.Assembly.GetCustomAttributes(typeof(DbLinqAttribute), > false).Length > 0) > { > IList<Type> types; > if (!interfaceImplementations.TryGetValue(i, out types)) > interfaceImplementations[i] = types = new List<Type>(); > types.Add(type); > } > } > } > > This is less than ideal for two reasons: > > 1. It uses Assembly.GetTypes(), which thus "pulls in" private types which > we probably don't care about. > 2. It increases memory requirements, as we're loading more Type instances > than we actually need. > 3. It increases disk usage (as more Reflection information needs to be read > from-disk to populate the Type instances). > 4. It's slower than it could be, due to (1), (2) and (3). > > (1) is "easily" fixed by using Assembly.GetExportedTypes(), which only > returns public types, but the biggest performance and memory issues are due > to (2) and (3). > > A better solution (in terms of memory and execution time) is to use an > assembly-level attribute: > > // within DbLinq.dll: > [AttributeUsage(AttributeTargets.Assembly)] > public class DbLinqProviderAttribute { > public DbLinqProviderAttribute(Type providerType); > public Type ProviderType {get;} > } > > // within e.g. DbLinq.Sqlite.dll > [assembly:DbLinqProvider(typeof(SqliteVendor))] > > This turns the O(n*m) (n=types, m=interfaces for each type) algorithm used > in ReflectonObjectFactory.Parse() into an O(1) algorithm, improving > execution time and lowering memory requirements (as we don't need to > allocate a potentially large array from Assembly.GetTypes(), etc.). > > The downside is that it slightly complicates the provider assembly, as they > need to use the DbLinqProvider attribute, but I think this may be > worthwhile. > > However, my biggest problem with the algorithm isn't within Parse() but > instead within ParseAppDomain(): > > 4. It processes most assemblies within the current AppDomain (and *only*those > assemblies). > > This limitation turned up when I was creating the DbLinq.SqlServer_test_ndb > project: it required that I have a strong reference to the DbLinq.SqlServer > assembly from my test assembly. > > The problem, specifically, is the use of the NullConnection type, e.g. from > MsSqlDataContextTest.cs: > > return new DataContext(new NullConnection(), new AttributeMappingSource()); > > In this case, we're not providing a connection string (deliberately, as we > don't actually want to connect to a database), and thus there is no explicit > reference to the provider that we want to test. This is undesirable; it's > only acceptable for now because the default provider is the SqlServer > provider, which is what I was testing, but this should not remain the > situation for long. > > Thus, a question: when using the > DataContext(IDbConnection,MappingSource)constructor, how should we specify > which provider assembly should actually > be used? The current code within DataContext.cs doesn't support using an > IDbConnection with a non-SqlServer provider: > > private void Init(IDatabaseContext databaseContext, MappingSource > mappingSource, IVendor vendor) > { > if (databaseContext == null) > throw new ArgumentNullException("databaseContext"); > > _VendorProvider = ObjectFactory.Get<IVendorProvider>(); > if (vendor == null) > Vendor = > _VendorProvider.FindVendorByProviderType(typeof(SqlClient.Sql2005Provider)); > else > Vendor = vendor; > > Non-SqlServer providers aren't supported because *vendor* will be null, > thus prompting Init() to try to find the SqlClient.Sql2005Providerprovider. > Oops. > > Possible solutions would be to check to see if the IDbConnection instance > implements the IVendor interface, and use that if appropriate (though this > doesn't seem quite right, given the IVendor.CreateDbConnection() method), > or have the IDbConnection type implement IVendorProvider (and ignore the * > providerType* parameter in the > IVendorProvider.FindVendorByProviderType()method). > > I'm not really sure what the ideal solution here is, and would welcome any > additional input. > > Thanks, > - Jon > > > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "DbLinq" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/dblinq?hl=en -~----------~----~----~----~------~----~------~--~---
