Just for information, Jiri is working on point 1: moving classes to
DbLinq.Data.Linq and make them stick to MS linq to SQL specifications.
Since I gave point 3 to Pablo (splitting strict and extended
features), I only keep the point 5 for me, which is a good load
balancing :)
And I just wish to thank everyone on the project for making DbLinq a
very good project.
The code is getting cleaner, we will provide a strict and an extended
version, we will support more and more databases...
It is getting so good that the Mono team is interested in the
project...
However System.Data.Linq should not to implement any interface.
In MONO_STRICT mode, you do not have to worry about non-public
interfaces. IMTable and IQueryText will become internal in
MONO_STRICT mode, right?
Atsushi Eno
what about composition instead of inheritance? perhaps an
internal-proposes wrapper that implements those interfaces?
Atsushi Eno
Currenty tey are passed as parameter in datacontext constructor.
Besides vendors projects currently use classes that will be internals
on strict mode.
That is a problem since one of the best features of dblinq is that
lose coupling with vendors.
What do you thing about this stuff?
Hmm, I noticed that there is some mess on how to do with those
vendor API:
- We cannot expose extra public types in System.Data.Linq.dll.
That means, System.Data.Linq.dll cannot expose interfaces
such as IVendor, ISchemaLoader and ISqlProvider.
- On the other hand, for those vendor implementations they have
to be public somewhere.
- That likely means, they must reside in some different assembly
(unless we use some reflection trick).
- If you are to create different assembly for those interfaces,
you would like to add the default implementations, which likely
depend on existing types in System.Data.Linq.dll (in MONO_STRICT
mode). Since System.Data.Linq.dll needs those vendor API
after all, it likely requires some cyclic builds.
So ... if I am right, we'll need another assembly than
System.Data.Linq.dll anyways.
Atsushi Eno
So ... if I am right, we'll need another assembly than
System.Data.Linq.dll anyways.
Hi, complicated dudes.
As probably already explained, we will split the source code files in two categories for each class/interface subject to extensions:
- the MONO_STRICT part, following the strict specifications is in a file (let's say "MyClass.cs")
- the extended part is stored elsewhere (let's say "MyClass.Extended.cs").
If this class implements a strict interface, then we write it in the strict file. This way we can have some other interfaces without problem for
If this class also implements an extended interface, then we declare this in the .Extended.cs file (if we want to keep only a single, we may place all .Extended.cs files into a big #if !MONO_STRICT / #endif).
Regarding the fact of exposing or not an internally required interface when in strict is probably something like:
--------------------------------------------------
#if MONO_STRICT
internal
#else
public
#endif
interface IVendor
--------------------------------------------------
So with this, everybody should be happy :)
So it is easy to make those default implementations stick to a specific database, like SQL Server, and then give the core a default provider
No problem: we can place a strict constructor in the MONO_STRICT file, and place extended constructors in .Extended.cs files.
The default constructor for us would use the default Vendor implementation (the one that's already in the core).
Pablo Iñigo Blasco wrote:
> So ... if I am right, we'll need another assembly than
> System.Data.Linq.dll anyways.
>
>
> I aggree in all of point that you said. However another dll is another
> kind of incompatibility between mono and MS.Net. A lot of applications
> would not work due they haven't that new assembly.
That is nonissue. For example our System.Data.dll uses Mono.Data.Tds.dll
which isn't of course used in .NET.
> IMHO in strict mode we sould sacrifice some features in favour to
> compatibility with MS.Net.
If we have different assembly than System.Data.Linq.dll that exposes
those vendor interfaces, it will still assure extensibility.
(Your remaining points are based on the understanding that
sys.data.linq.dll must not depend on anything external. So I skip them.)
Atsushi Eno
That is nonissue. For example our System.Data.dll uses Mono.Data.Tds.dll
which isn't of course used in .NET.
If we have different assembly than System.Data.Linq.dll that exposes
> IMHO in strict mode we sould sacrifice some features in favour to
> compatibility with MS.Net.
those vendor interfaces, it will still assure extensibility.
Pablo Iñigo Blasco wrote:
> That is nonissue. For example our System.Data.dll uses Mono.Data.Tds.dll
> which isn't of course used in .NET.
>
>
> Ok. You have convinced me.
>
> Nonetheless that supposes that Mono.Data.Tds.dll (or in our case a
> theoretical DbLinq.Common.dll ) is registered in the GAC.
> ie: if I were to use Mono/System.Data.Linq.dll as an external dll in a
> Ms.Net project I should also to add that theoretical DbLinq.Common.dll.
> OK I understand that this kind of situations are strange and they don't
> matter enough, so I your proposal seem the best option for maintaining
> compatibility.
Mono's System.Data.Linq.dll must be regarded as totally different
from that assembly from .NET. That is like usual side-by-side
assemblies. So, in theory, there is nothing special that *our*
System.Data.Linq.dll requires DbLinqSomething.dll in the GAC (when
deployed there).
Though I don't think you can add mono's System.Data.Linq.dll without
changes, because it has the same assembly identity as .NET has.
You'll have to rename our assembly after all.
> Another question is: what do you think about IVendor parameter of
> DataContext constructor?
Some DataContext construtcors take MappingSource. In attribute-based
mapping, there is System.Data.Linq.Mapping.ProviderAttribute that
indicates the type of "SqlProvider" as its Type property. (There
should be similar XML syntax for XmlMappingSource.)
Syntactically it allows any kind of type. So we can pass
typeof(FooVendor) there. In DataContext, we can assume that the
type either is derived from SqlProvider or implements IVendor etc.
> Thanks to Pascal, you and rest for answering all of these questions, now
> I see the path to SxSVersion cleaner.
Thanks from me too :)
> If everybody agrees, I will start extracting dependencies of specific
> vendors and DbMetal to another project DbLinq.Common.csproj.
> Dependencies include SchemaLoader and SqlVendor classes...
No problem from my side; it's up to Pascal :-)
Atsushi Eno
It would be useful if DbMetal generated entity code can be used with
different databases without changing generated code.
Requiring hard-coded provider attribute for generated DataContext class
prevents this.
Andrus.
"How to indicate the default Provider" is a different issue.
In MONO_STRICT land we could indicate it by some custom configuration
section.
Atsushi Eno
I understood when you said that the default data context constructor
would use the default vendor, but how to use others vendors if?
Of course the most important thing is that everybody agrees on how to
do that. Personally I just want to understand the point of view of
each one.
I understand that is less sexy to have two dlls for dblinq.
Another way could be to have two projects in strict mode and in the
otherwise only one. Cs files would be shared. Like we currently do in
tests projects.
Just an opinion.
Regards.
#if MONO_STRICT
internal
#else
public
#endif
interface nonpublicableClassOrInterfaceInStrictMode
#if MONO_STRICT
using System.Data.Linq;
#endif
#if MONO_STRICT
using DataLinq = System.Data.Linq;
#else
using DataLinq=DbLinq.Data.Linq.DataContext;
#endif
#if MONO_STRICT
using DataLinq = System.Data.Linq;
#else
using DataLinq=DbLinq.Data.Linq;
#endif
I'd rather like a pattern like this:
#if MONO_STRICT
namespace System.Data.Linq.XXX
#else
namespace DbLinq.Data.Linq.XXX
#endif
Just because your pattern confuses ReSharper (and I can't live without it :)). But feel free to commit your patch anyway, we can arrange this later.
Regarding acceptance of you patches, correct me if I'm wrong, but your submissions always get a (motivated) answer. DbLinq is having a difficult time, because a lot of things are changing right now (Mono, strict/extended, new sql engine).
I'm currently working on moving all necessary stuff to *.Data.Linq namespace, after this, the *.Linq namespace should be useless. It takes time, because the insert/update and delete clauses still use the old engine, so I need to switch to new engine (copy/paste/adapt). I expected it to be finished last week-end, but I'm afraid it will require one or two more weeks.
You can already work on pieces already present in *.Data.Linq, since they are close to a "final" version.
My current gut feeling is that you cannot really make it to build
System.Data.Linq.dll from DbLinq source just with MONO_STRICT
condition (in terms of vendor extensibility issue) and my wrapper
approach (i.e. write System.Data.Linq.dll as a wrapper to DbLinq)
would be still easier.
If your attempt results in success that's of course great ;-)
Atsushi Eno
> jabber/gtalk: pas...@jabber.fr <mailto:pas...@jabber.fr>
> msn: pas...@craponne.org <mailto:pas...@craponne.org>
>
> >
===============================================================================================
Prerequisites: we must have different csprojs for strict(System.Data.Linq.csproj) and non strict modes(DbLinq.csproj).
In first place because assembly references, we cannot reference System.Data.Linq in strict mode for evident reasons.
In second place because extensibility. if we want to have public Vendors they mustn't belong to System.Data.Linq project.
In third place because design, useless files in strict mode, useless files in non strict mode.
In fourth place for suitability: project symbols, builds...
In fifth place because csprojs does not matter in Mono, that won't use DbLinq.csproj but makefiles.
=================================================================================================
First stage: Build a System.Data.Linq with correct public classes.
1 - In strict mode we should locate all classes into System.Data.Linq.* namespace (even older classes, they likely will disappear in the future)
- DbLinq.Data.Linq.* would be moved to System.Data.Linq.*
- DbLinq.* would be moved to System.Data.Linq.Base (this namespace should disappear in the future)
(as we are currently doing we would use a preprocessor directive for not annoy the non-strict build)
2 - Some directives will be wrong in strict mode ie: using DbLinq.* (ie: System.Data.Linq.Base.XX won't exist in non strict build) -> apply also using preprocessor directives in that points.
3 - Make all classes visibility internal except the "key classes" (DataContext, DataTable...) also using preprocessor directives
4 - Add rest of classes of System.Data.Linq to from current mono svn repository (since this project does not references MS/System.Data.Linq.dll). Remove duplicated classes (DataContext, DataTable...)
5 - Remove some "using System.Data.Linq" since in strict mode we are such namespace
(we should use a preprocessor directive for not annoy the non-strict build)
6 - To Add some using directives in strict code ie: System.Data.Base (but they would disappear in the future)
All those task don't annoy the current non-strict build.
Pascal work can continue like nothing happened.
Preprocessor directives explosion is the main threat in this step. But at least they would be located in 3 known places:
- using blocks
- namespace declarations
- classes visibility
At the end of this stage we would have:
- a non strict mode project that works and builds like now.
- a strict mode project builds itself but:
- It isn't builds in rest of projects of dbLinq (tests, vendors, examples, dbMetal..).
- Maybe Test_Nunit_Mssql_strict.csproj builds (removing DbLinq.dll and DbLinq.SqlServer.dll reference).
- And maybe default vendor lets that some those test work fine.
==============================================================================================================================
Second stage: Correct classes interface
In this step we must to avoid preprocessor directives. That could be fatal for the maintainability,
So this step affect to the non strict mode design.
1 - From those few "key classes" (DataContext, DataTable...) take public members that does not match with .NET interface and do:
- set them as internal.
- that change will break the other projects (Tests, Examples, DbMetal) until the point 3.
2 - Mark those methods with a prefix (ie: "public void foo()" to "internal void strict_foo()")
3 - Create a extension.cs file with public methods, they only will be stubs. (ie: "public void foo(){strict_foo();}").
(This file would not be included just in non strict csproj)
4 - Move constructors that does not match with .net to the extensions file.
Code conventions for Extensions files:
- Only "key classes" should contain extension files.
- Extension files methods calls should be forbidden inside neither DbLinq.csproj nor System.Data.Linq.csproj files (you should use the internal ones).
- Extensions files just define the interface of DbLinq.Data.XXX to outside of the project (DbMetal,Examples,Tests...)
- They also contains non standard constructors. That constructors shouldn't be used in DbLinq Project.
At the end of this stage we would have:
- A DbLinq project that works and builds like before but with a few extensions files.
- A System.Data.Linq.dll that has correct classes and correct methods, but is incompatible with (DbMetal, Examples, Tests..) and does not have Vendors extensibility.
===============================================================================================================================
Third stage: Vendors in strict mode
1 - Create a new csproj Vendors.csproj with needed classes and interfaces to vendors projects.
2 - Create code for managing ProviderAttribute for vendors extensibility. Maybe this code will be useful in both System.Data.Linq.csproj and DbLinq.csproj
3 - How will it affect to DbLinq.csproj? There are two choices:
A - DbLinq.csproj keep vendors classes.
+ only one assembly for DbLinq.csproj, everything work like before
- DbMetal, Vendors projects won't build with System.Data.Linq.dll but it can be solved duplicating each csproj of the solution and referencing our System.Data.Linq.csproj and Vendors.csproj
B - DbLinq.csproj lose vendor classes (like System.Data.Linq.csproj)
- two assemblies referenced in all projects.
+ no csproj explosion.
At the end of this stage everything should work correctly with System.Data.Linq.csproj and DbLinq.csproj.
Pablo Iñigo Blasco wrote:
> The wrapper is an option, of course each implementation will have
> problems, but IMO it is possible and better with MONO_STRICT
> preprocessor directive.
Just curious, what's the disadvantage of wrapper approach? (there
should be some, as you think it worse.)
Since DBLinq fills missing pieces in itself and the API mismatch
issue should go anyways, the only disadvantage was that it requires
another assembly (S.D.Linq.dll itself), which actually apply to
other approaches too.
Atsushi Eno
Just curious, what's the disadvantage of wrapper approach? (there
should be some, as you think it worse.)
So here are a few comments about your points:
1.1. Moving all *.Linq classes to *.Data.Linq is a bad thing to me, since I will lose track of what's done (*.Data.Linq) and what remains to be done (*.Linq). When I'm finished moving all needed classes to *.Data.Linq, all *.Linq classes will be obsolete and can easily be removed.
1.3. In theory, all *.Data.Linq.* classes should be internal, except of course the strict ones. This means that all Sugar classes should always be internal, for example. As of today, there is no need to make them public.
2.* very smart move :)
3. I'm not sure I understand: could you give me a few more details about each solution?
Regarding the two project files, that could be an option, if the two project files are included in the same solution: this way, we will always be sure that both projects always build (because my main concern is to keep both projects alive).
As you have noticed, your suggestions are not always lost :)
What is the need for point 1.1? After adapting all contents to *.Data.Linq, all the *.Linq will disappear,
so I don't understand why you need System.Data.Linq.Base. What do you plan to move there?
This time it is about your proposal. (I had enough time to read it and
some sleep in this jetlagged Boston stay ;)
Comments inline:
They are just stubs. You don't have to take them (and code formatting
difference will annoy you ;-)
I'm mostly interested in this stage: How can the implementors of
IVendor (especial an external implementor) reference internal abstract
(or possibly non-abstract) default Vendor implementation in strict mode?
The adapter type indicated by ProviderAttribute has to be implemented
by each IVendor implementor and hence its API must be exposed somewhere.
(Plus, I'm not sure if my ProviderAttribute solution is okay for
everyone ;-)
Atsushi Eno
It's almost not about technical issue though ...
Pascal Craponne wrote:
> Writing an adapter (wrapper) requires to work on a stable basis, and at
> the moment, DbLinq is everything but a stable basis.
We can take any snapshot of DBLinq to build the wrapper.
> An adapter is also useful when the requested interface doesn't exist. In
> our case, the requested interface exists, and there is even more (with
> the non-strict extensions). This is the "more" that we want to cut out,
> and not to transform the existing.
It is out of concern anyways, but the fact was that I find difficulty in
how to implement missing stuff in DBLinq (and hence some members were
left not-implemented).
> In fact the wrapper is a good stategy when everyone working on DbLinq is
> dead, and there is no more support on it (that's the usual business case
> for an adapter)... ;) Until then, we can probably have a more efficient
> developement strategy by developping things only once (and Pablo is full
> of energy :)).
The problem is rather about that it is Linq to SQL, not DBLinq, which
is unlikely improved and hence it will block DBLinq growth at some
stage. And the API is out of our control.
When both sides work together at API level, your point is still valid.
But we work together only to *implement* the API. (When contributing
to non-strict mode, there is no *both* sides ;-) that's a different story.)
> To me the DbLinq-Mono association is a win-win case because we work on
> the same project: if we have two projects (conceptually speaking), which
> are DbLinq and the DbLinq-wrapper, there's no need to work together, and
> I think that both teams have to lose with this situation.
Having separate builds does not mean we both lose. It actually rather
brings more flexibility (we could stick to old dblinq build and give
feedback to you guys), which makes me feel it's better. If there
is no one interested in keeping it up to date, then the cooperation
will stop at that stage. It is the nature of projects that we should
not deny ;) and still does not block further improvements from you guys.
Atsushi Eno
> On Tue, Jun 24, 2008 at 06:06, Atsushi Eno <ats...@ximian.com
> <mailto:ats...@ximian.com>> wrote:
>
>
> Hi,
>
> Pablo Iñigo Blasco wrote:
> > The wrapper is an option, of course each implementation will have
> > problems, but IMO it is possible and better with MONO_STRICT
> > preprocessor directive.
>
> Just curious, what's the disadvantage of wrapper approach? (there
> should be some, as you think it worse.)
> Since DBLinq fills missing pieces in itself and the API mismatch
> issue should go anyways, the only disadvantage was that it requires
> another assembly (S.D.Linq.dll itself), which actually apply to
> other approaches too.
>
> Atsushi Eno
>
>
>
>
>
>
> --
> Pascal Craponne
>
When I was writing it, the most significant problem was impedance
mismatch that is being solved by this SxS effort.
BTW take my opinion as "you don't have to go messy way, there is
likely an easier solution" rather than "you had better discard your
attempt and go along with my proposal" ;-) That's not my intention.
Atsushi Eno
Extensibility in MONO_STRICT mode is not a "requirement", but at least
I personally love such an extensible implementation much more, and I'm
sure you guys also do too ;-)
But if the only solution is to use InternalVisibleToAttribute, then
I'm fine with it. Actually I see the only possible solution there.
Atsushi Eno
I'm mostly interested in this stage: How can the implementors of
IVendor (especial an external implementor) reference internal abstract
(or possibly non-abstract) default Vendor implementation in strict mode?
The adapter type indicated by ProviderAttribute has to be implemented
by each IVendor implementor and hence its API must be exposed somewhere.
The adapter type indicated by ProviderAttribute has to be implemented
by each IVendor implementor and hence its API must be exposed somewhere.
(Plus, I'm not sure if my ProviderAttribute solution is okay for
everyone ;-)
Currently, vendors do not (and must not) reference at all any database driver, allowing the used to choose its own implementation and version.
> An adapter is also useful when the requested interface doesn't exist. InIt is out of concern anyways, but the fact was that I find difficulty in
> our case, the requested interface exists, and there is even more (with
> the non-strict extensions). This is the "more" that we want to cut out,
> and not to transform the existing.
how to implement missing stuff in DBLinq (and hence some members were
left not-implemented).
The problem is rather about that it is Linq to SQL, not DBLinq, which
is unlikely improved and hence it will block DBLinq growth at some
stage.
And the API is out of our control.
BTW take my opinion as "you don't have to go messy way, there is
likely an easier solution" rather than "you had better discard your
attempt and go along with my proposal" ;-) That's not my intention.
the idea to include vendors code in the forthcoming System.Data.Linq.csproj
Then the approach looks fine to me too :)
Atsushi Eno
Pablo Iñigo Blasco wrote:
> > An adapter is also useful when the requested interface doesn't
> exist. In
> > our case, the requested interface exists, and there is even more
> (with
> > the non-strict extensions). This is the "more" that we want to
> cut out,
> > and not to transform the existing.
>
> It is out of concern anyways, but the fact was that I find difficulty in
> how to implement missing stuff in DBLinq (and hence some members were
> left not-implemented).
>
>
> Like we have *.Extensions.cs files included exclusively in
> DbLinq.csproj, we could have other *.Extensions.cs included exclusively
> in System.Data.Linq.csproj.... Anyhow I agree that the model is getting
> more and more complex... :-/
I misused past tense; the fact was I found it difficulty there. That is
all about past tense talk. As I've already said, dblinq is getting
API compatible with S.D.Linq (thanks to SxSVersion work), so this is
really out of concern.
> The problem is rather about that it is Linq to SQL, not DBLinq, which
> is unlikely improved and hence it will block DBLinq growth at some
> stage.
>
>
> if those improvements concern just API I think that it is solved with
> extensions files. If DbLinq had more functionality that would be great
> great, we just should hide that methods using the extension file
> convention (All public members exclusively of DbLinq must be in a
> Extension.cs file not included in System.Data.Linq.csproj)
>
>
> And the API is out of our control.
>
>
> As you said, it likely it won't change.
Then that means, the original concern that Pascal wrote is not existent.
Let's first finish current attempt to the end (the third stage) to see
if everything works fine. The primary concern wrt wrapper approach
is/was that dblinq has/had couple of API/design incompatibility.
With compatible API, it would just need a couple of hours' hacking.
Atsushi Eno
I'm lost. Why changing DbLinq's organization if there is a new project file for Mono System.Data.Linq?
Regarding DbLinq, we can keep the whole thing as it is:
- a core: DbLinq exposing a public IVendor & friends
- vendors: DbLinq.*
Regarding Mono:
- a unique assembly, with internal IVendor, and internal implementations
- if you want to keep extensibility, we'll be out of MS scope anyway, so we can make the IVendor interface just public.
What's wrong with that?
Hence, we cannot keep extensibility in Mono in your opinion.
Atsushi Eno
I'm OK with any approach Pablo would actually take. The final choice
would rather be dependent on whether it is possible or not.
It turned out that Mono people does not really care about losing
extensibility over .NET API, so I, as part of that community, wouldn't
mind much either.
Atsushi Eno