Atsushi Eno
Actually r927 broke MONO_STRICT build, where no concrete DB providers
cannot be referenced (there is no reference to FirebirdSql, Ingres,
Pgsql etc. etc.).
It should be done by some reflection based factories that provides
those connections, without using strong (straightforward) references
to those connection types.
Atsushi Eno
Jiri, thanks for taking care of it. Now it should build (it builds
at least with System.Data.Linq.csproj). It's already 6:30 AM, so
I'll try it on mono tomorrow.
Atsushi Eno
For now I'm going to sleep but if
Atsushi Eno
- Assembly.Load("System.Data.Linq.dll" won't work, since it is
not in current current directory but in the GAC (you can try
Assembly.Load("System.Data.dll") on .NET - it won't work).
For now I just skipped assembly load phase by just supplying
typeof(DataContext).Assembly (= S.D.linq.dll itself).
I'm not sure if it doesn't really matter in DBLinq land. It will
fail when DbLinq.dll and DbLinq.VendorFoo.dll reside differently.
- DbLinq.Vendor.Implementation.Vendor.CreateDbConnection() tries
to create IDbConnection and then it simply fails, saying:
> DataContext ctor: Assembly load failed for System.Data.SQLite.DLL:
> System.IO.FileNotFoundException: Could not load file or assembly
> 'System.Data.SQLite.DLL' or one of its dependencies. The system
> cannot find the file specified.
> File name: 'System.Data.SQLite.DLL'
I guess it may happen to non-strict version of DBLinq when referenced
-by-name assemblies do not exist at run-time (only in-use DB provider
assembly has to exist, right?).
I also noticed that .ctor(string, MappingSource) could be implemented
easily. I'm attaching a patch. (Note: it contains mono workaround
for the first issue. Second issue is not fixed.)
Atsushi Eno
Index: src/DbLinq/Data/Linq/DataContext.cs
===================================================================
--- src/DbLinq/Data/Linq/DataContext.cs (revision 116918)
+++ src/DbLinq/Data/Linq/DataContext.cs (working copy)
@@ -106,12 +106,6 @@
Init(new DatabaseContext(connection), null, null);
}
- [DbLinqToDo]
- public DataContext(string fileOrServerOrConnection, MappingSource mapping)
- {
- throw new NotImplementedException();
- }
-
/// <summary>
/// Construct DataContext, given a connectionString.
/// To determine which DB type to go against, we look for 'DbLinqProvider=xxx' substring.
@@ -121,14 +115,22 @@
/// DbLinqProvider=Mysql
/// DbLinqProvider=Oracle etc.
/// </summary>
- /// <param name="connectionString">specifies file or server connection</param>
+ /// <param name="fileOrServerOrConnection">specifies file or server connection</param>
[DbLinqToDo]
- public DataContext(string connectionString)
+ public DataContext(string fileOrServerOrConnection)
+ : this (fileOrServerOrConnection, null)
{
+ }
+
+ [DbLinqToDo]
+ public DataContext(string fileOrServerOrConnection, MappingSource mapping)
+ {
#region DataContext connectionString ctor
- if (connectionString == null)
- throw new ArgumentNullException("connectionString");
+ if (fileOrServerOrConnection == null)
+ throw new ArgumentNullException("fileOrServerOrConnection");
+ string connectionString = fileOrServerOrConnection;
+
System.Text.RegularExpressions.Regex reProvider
= new System.Text.RegularExpressions.Regex(@"DbLinqProvider=([\w\.]+)");
@@ -146,7 +148,7 @@
#if MONO_STRICT
//Pascal says on the forum:
//[in MONO] "all vendors are (will be) embedded in the System.Data.Linq assembly"
- assemblyToLoad = "System.Data.Linq.dll";
+ assemblyToLoad = null;
vendorClassToLoad = match.Groups[1].Value; //eg. "MySql"
#else
//plain DbLinq - non MONO:
@@ -172,8 +174,12 @@
Assembly assy;
try
{
+#if MONO_STRICT
+ assy = typeof (DataContext).Assembly;
+#else
//TODO: check if DLL is already loaded?
assy = Assembly.LoadFrom(assemblyToLoad);
+#endif
}
catch (Exception ex)
{
Regardless of whether current implementation strategy is to change
or not, Dynamic type loading will also happen for loading DB
provider assemblies (e.g. System.Data.SQLite.dll), like currently
DbLinq.Vendor.Implementation.Vendor.CreateDbConnection() does.
To not load assembly dynamically, you will have to add dependencies
onto all DB providers, which you don't want (unless I miss some
other possibilities).
Atsushi Eno
- It is the database driver vendor who claims that a future version
of the assembly is compatible with older versions of the driver or
not (by "publisher policy file" i.e. policy.*.*.dll in general).
- Usually a user (dblinq here) should depend on specific version of
the dependency assemblies in each version of his or her application
- A user (we) can finally determine whether a future version of the
assembly is compatible with older versions in respect to his or her
application. It can be specified by our assembly configuration
(/configuration/runtime/assemblyBinding/dependentAssembly).
While we would likely want to avoid loading "duplicate" assemblies
(not precisely though; they have different versions), we can first
iterate Assemblies in CurrentDomain, and then try Assembly.Load() with
fully qualified name. Then users don't have to add extra code to load
the driver assembly in prior to use dblinq.
Adding custom configuration section may also look like a solution, if
we want to let users to make first decision on which Type should be
regarded as the target driver (it is typical scenario). But the problem
here is that it works only when the dependent assemblies MUST exist
*while proving the target driver*. Otherwise it will raise an error
saying that the configuration system cannot find the target Type.
(Am I understanding the situation correctly? I'm unsure.)
Atsushi Eno
> jabber/gtalk: pas...@jabber.fr <mailto:pas...@jabber.fr>
> msn: pas...@craponne.org <mailto:pas...@craponne.org>
>
>
> >
Pascal Craponne wrote:
> I may die alone (at least), but I still don't agree:
Well, it is all about "when we couldn't prove the target
vendor/provider after iterating assemblies in the current domain.
It is not to stick to specific driver (at least what I intended).
Discussed details below.
But before digging in depth, I'd like to confirm whether we take the
approach to check assemblies in the current domain. Right now
MONO_STRICT doesn't work at all for connectionString-based use due to
the current assembly load strategy.
> - Sticking to a driver will cause problems where there are two driver
> implementations, such as Oracle drivers, where there are two different
> implementations, MS and ODP.
I'm curious - can/should they be the same implementation while the
"vendors" are different? Is it still valid when we start to consider
creating IDbConnection instance from connection string i.e. how can
we distinguish a connection string for OracleClient and for ODP.NET
within one vendor API? Add another connection string item such as
"OracleDriver=ODP" ?
> - Sticking to a version will require DbLinq to be built and integrate
> each new version. Today DbLinq supports 7 databases. How many releases
> will it imply each year? How many releases when DbLinq will support 10
> databases? Too many.
Note that I didn't suggest to "actually" stick to specific versions
of database drivers. As I wrote in the previous message, they should
be redirected to newer versions as long as the driver vendors ship
policies. Or you could even put assembly configuration for dblinq.
That is, for each <bindingRedirect> element you just give the oldest
supported version of the driver like:
<dependentAssembly>
<assemblyIdentity name="MySql.Data" publicKeyToken="(snip)"
culture=""/>
<bindingRedirect oldVersion="0.0.0.0-65535.65535.65535.65535"
newVersion="(the oldest supported version" />
</dependentAssembly>
seealso http://msdn.microsoft.com/en-us/library/9w519wzk(VS.71).aspx
It'd happen just once. I don't think there really is such a task to
manage every driver every year, unless they became very different
(probably like Npgsql -> Npgsql2, where we should really care,
at least the assembly name has changed).
> - Sticking to a version will also leave behind the applications who
> can't upgrade to the version linked by DbLinq.
So it won't happen, unless the driver assembly name changes (and
even it might not happen as you seem to have some magic to have
OracleClient and ODP.NET coexist within a vendor implementation).
> Each actor has its responsibility and it's better if the application has
> the responsibility to assemble all parts and make a consistent result.
>
> Atsushi, are you talking in your message about loading vendor or
> database driver?
Both. But note that under MONO_STRICT I don't need any trick for
loading vendors ;-)
Atsushi Eno
> > <mailto:gmo...@gmail.com <mailto:gmo...@gmail.com>>> wrote:
> >
> >
> > Pascal, Astushi - Ohayo gozaimasu & Bon soir,
> > seems that both of you like scanning the AppDomain for the
> IVendor
> > class and the IDbConnection implementation.
> > I like it also, because it results in fewer assumptions and
> shifts
> > responsibility to the user. Should we go ahread with that
> approach?
> >
> >
> >
> >
> >
> > --
> > Pascal.
> >
> > jabber/gtalk: pas...@jabber.fr <mailto:pas...@jabber.fr>
> <mailto:pas...@jabber.fr <mailto:pas...@jabber.fr>>
> > msn: pas...@craponne.org <mailto:pas...@craponne.org>
> <mailto:pas...@craponne.org <mailto:pas...@craponne.org>>
Atsushi Eno
Assembly name is still npgsql.dll
http://pgfoundry.org/forum/message.php?msg_id=1003866
So I don't understand why you wrote that assembly name has changed.
Andrus.
Atsushi Eno
I agree to most of the points. I only have a few concern:
> Examples:
> - fully qualified vendor and connection
> "DbProvider=DbLinq.PostgreSql.PgsqlVendor, DbLinq.PostgreSql;
> DbConnection=Npgsql.NpgsqlConnection, Npgsql; ..."
> - partially qualified: "DbProvider=DbLinq.PostgreSql.PgsqlVendor;
> DbConnection=Npgsql.NpgsqlConnection; ..."
> - ID qualitifed: "DbProvider=PostgreSQL; DbConnection=PostgreSQL; ..."
The first vendor name looks rather like a partial name, and I'm not
sure if it works fine with Assembly.Load*() methods. (There is
Assembly.LoadWithPartialName() but it is obsoleted.) A fully
qualified name involves version numbers, which does not seem good.
And I don't think the second "partially qualified" case is useful.
I have no preference on which/how dependencies will be loaded, as
long as it does not force users to add extra code (such as loading
dependencies in prior to the actual use). DBLinq is designed to be
dependency version agnostic and I show doubts on that principle
only when it rather looks like a blocker to more features.
Atsushi Eno