-
Notifications
You must be signed in to change notification settings - Fork 821
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Entity framework work for release 2.1.0 #110
Conversation
I just had an idea for another approach to the nuget/EF problem... Would it be possible to split off the entities framework-dependent code into another DLL altogether? If so, we could package one Npgsql nuget without any EF stuff, and simple two add-on packages - EntityFramework (for EF6) and EntityFrameworkLegacy (for pre-EF6). If possible, this definitely seems like the cleanest approach here. I'll take a look at this, but I'll need the help of someone who actually knows EF a little... |
Hi roji. I'll help you as far as I can. btw Here is my usage: I'm rewriting my company's obsolete ERP system built on 4th Dimension. It has many tables. So I prefer database-first approach in EF. It is the reason I selected EF. (I also tried DbLinq, but it misses some important features) My development environment:
My way to deploy Npgsqls:
My tools for EF:
Note:
It is the research result obtained in last month. Sorry. I'll discuss about approach to the nuget/EF packaging problem, at next time. |
@kenjiuno, thanks for this info. I know you did a lot of testing/work on getting EF to work, I should have followed that more. Some quick comments/questions:
In general, my approach to EF was like to any other .NET dependent library: install it via nuget and it gets referenced in your project (no GAC or anything). I understand this approach may be insufficient for EF (because of the special relationship to VS), if this is truly the case I can try to look for a "standard" nuget way to get a DLL into the GAC? |
This is what I wrote in the #109 before seeing Shay's message to continue the discussion here: "I liked your strategy of the three packages. Those three packages would cover all the possible scenarios for Npgsql users. I also think we should share this question to devel-list." And by seeing your new idea of using add-ons, I think this would be very good too. I just don't know how much complicated it would be to get the EF code split. Maybe we would need to make those EF assemblies a friend assembly of Npgsql so they can access Npgsql internals. But I think that having a non EF Npgsql, a 4.3EF and a current 6.0EF would cover all the scenarios a developer would need, wouldn't they? I think the problem with edmgen, from the little experience I have, is that it looks in the GAC and in the machine.config the configuration to use the providers. I couldn't find a switch to make edmgen works otherwise. I didn't try to create a custom edmgen.exe.config file in my current folder and see if it loads the configuration from there though. If it does, I think we could start to ship custom edmgen.exe.config files preconfigured for Npgsql. The only way I could get edmgen using an Npgsql version without installing in GAC was when I put it as the executable to debug the Npgsql project. But of course this isn't the ideal situation. I'd bet in the edmgen.exe.config file or something like that to make edmgen look for Npgsql in another place other than the GAC. I hope what I said makes any sense. |
Hi.
I'm sorry. I have confused you too much. Npgsql can be distributed in the nuget's standard way. I'll welcome it! I forgot to say: why Npgsql and NpgsqlEF6 should be separated? It is problem about assembly's qualified name. For example: the following assembly is recent Npgsql's assembly sign.
It may be ...
We cannot identify it easily... This is first problem. Next problem is about GAC. About VS Designer support version of Npgsql, it is said Npgsql should be put into GAC. http://fxjr.blogspot.jp/2011/05/npgsql-design-time-support-preview.html And then, if your Npgsql assembly has same assembly signature like
your version won't be loaded. because MS's .NET runtime searches GAC at first, not our working folder. How the Runtime Locates Assemblies It may cause unpredictable problem in the future. So I thought the following combination will be better, if your nuget package shall be official release point.
I don't mind that you will prepare 3 nuget packages. My idea is just reminder, if you use same assembly signature in all 3 packages. If you need answer for each question, please go down the following line :) Hi.
I think Yes about DDEX support. DDEX requests InvariantName (Npgsql) to obtain DbProviderFactory class. http://msdn.microsoft.com/ja-jp/library/bb163767(v=vs.90).aspx It means we have to install Npgsql.dll into GAC, and then edit machine.config for DbProviderFactories. Otherwise, If you use VisualStudio 2012 for Desktop, edit WDExpress.exe.config instead, and then copy Npgsql.dll to Visual Studio install folder which they can find it. But, there is no problem about nuget support, nuget can install the assembly into VS project easily.
Yes, there is a little difference in way to get interface. http://entityframework.codeplex.com/wikipage?title=Rebuilding%20EF%20providers%20for%20EF6 About legacyEF, it is said like tightly coupled the EF provider to the DbProviderFactory.
And, we will add provider description in either App.config or machine.config so that ADO.net can find it.
About EFv6, provider element is needed to add manually. nuget may need support for it.
There are two Npgsql.
Continue with EFv6, connectionString is written by EntityDataModel designer or us.
Finally, generated context class refers connectionString by its name.
Probably yes. It is said VS2010 project can apply EF6 by nuget too. http://blogs.msdn.com/b/daisukei/archive/2012/08/17/entity-framework-5-ef5-ef-6.aspx VS2012 can do it too.
Sorry, I find yet no tooling targeting EFv6 directly. The reason why it can't be done is: EFv6 provider is not registered anywhere inside Windows. If you install EntityFramework 6.0.1 from nuget, nuget writes SQL Server's EFv6 provider information into App.config.
If we prepare our own EdmGen for EFv6, we will have to attach Npgsql EFv6 Provider within EdmGen package. btw EdmGen is provider independent. Any of SQLServer/Npgsql/Firebird/SQLite.net/etc can be applied if they support legacyEF. |
Thanks for the input. Let me try and play around with the add-on architecture, it may not be that difficult to split the EF-related code out, and that would be a very clean solution to the problem. We would then have an entirely separate project (NpgsqlEntityFramework), from which we'd generate two nuget packages - one for legacyEF and one for EF6. Then, whether you install the DLL into the GAC or not, based on whether you need DDEX/EdmGen/whatever is up to you... PS I sent an email to the devel list linking this discussion to get additional feedback. |
Hi. I see it is not good idea to put Npgsql into GAC in usual operation. Just FYI. It fires exception, if we have same provider name (Npgsql) in both App.config and machine.config.
|
OK, I've looked at the situation and I think I may have an idea how to solve it in the best way. I'm not talking about GAC, machine.config vs. App.config issues, only on how the package and use Npgsql and its EF components and deliver them to users (the GAC / machine.config discussion is also very important but I want to concentrate...). Background:
This allow us to do the following:
The advantage of the above is exactly one Npgsql nuget package, and exactly one Npgsql.EntityFramework6 add-on package. No more confusion on which version I have, does it support EF6 or not, etc. It does mean we need a new project, Npgsql.EntityFramework6, in the solution for the EF6 add-on. Npgsql and Npgsql.EntityFramework6 would share some of the same .cs source files (the EF-specific ones), but the EF6 project would compile with ENTITIES6. Hope that made sense and wasn't too long. Comments? |
Hi all, I don't remember exactly the syntax but it was something like: Dbproviderfactories Something like that. I hope it helps
|
Hi.
Great! It helps to resolve machine.config vs. App.config issues. I have tested some patterns with following App.config.
Tests:
Result: all passed. Test code:
|
Hi.
I think it is the realistic and the best idea for now. I agree with your idea!
I think shipping edmgen.exe.config is good idea. The developers can copy edmgen.exe from their .NET directory easily. And then, we can simply call edmgen.exe without: putting Npgsql/Mono.Security into GAC, and editing machine.config |
One more optimization on my above proposal... Rather than compile the EF code into Npgsql.dll for legacy mode, and relying on mono not trying to jit it, I propose to simply compile an Npgsql.EntityFrameworkLegacy.dll for pre-EF6. The NpgsqlFactory, which has to expose the legacy-EF NpgsqlServices, would load this DLL with runtime reflection (Assembly.Load()), and throw an exception if not found. So to sum it up: One Npgsql nuget, one Npgsql.EntityFrameworkLegacy nuget (for pre-EF6 users), one Npgsql.EntityFramework nuget (for EF6 and on). I'll probably work on this later today... Let me know if you guys have any input. |
Hi.
Ok. |
I'm actually planning to do this: Assembly.Load("Npgsql.EntityFrameworkLegacy, PublicKeyToken=5d8b90d52f46fda7") This ensures we only get our own proper DLL... |
Hi. I tested with Npgsql: Assembly.Load("Npgsql, PublicKeyToken=5d8b90d52f46fda7") It is good idea! |
+1 for this. This way if a user doesn't need the legacy EF support she doesn't even need to worry about possible jit or dependency problems. |
OK, I've been hacking at this for a while and I think it's close to finished (but not quite). Unfortunately personal life calls, darn. @kenjiuno, @franciscojunior and anyone else, please review this latest commit and left me know what you think. It looks big and scary but it really isn't - just a reorganization of the code into three cleanly-separated projects. Note that it's still WIP; the legacy EF mode still isn't done (I have a bit of reflection code to write). But most of the rest (specifically the EF6 mode) should work fine. It's really important for me to get feedback on this, both because I don't know EF as well as I should and because it's an important project structure change. Good night... |
Hi. Thanks. I have tested your commit, and here is patch kenjiuno/Npgsql@bedf593. It is for getting myApp/EdmGen/EdmGen06 working in my development computer. EDIT: fixed commit link |
I also tested it here and the project restructuring seems very nice. I noticed that you edited the 2013 project with vs. Net 2012 because it I could only test the nunit tests. I didn't test yet the entity framework Excellent work, Shay! I'll test more tomorrow. Thanks Kenji for testing that too.
|
- Reorganized the code into three projects/packages: 1) The Npgsql "core", fully functional ADO.NET and no EF 2) Npgsql.EntityFramework, an add-on for users of EF6 and above 3) Npgsql.EntityFrameworkLegacy, an add-on for users of EF5 and below - All EF-related code has been split off from Npgsql and into the Npgsql.EntityFramework directory - The same EF code is built via two projects: Npgsql.EntityFramework (defining ENTITIES6 for the new EF6), and Npgsql.EntityFrameworkLegacy (not defining it for pre-EF6). Still to be done: - Npgsql.NpgsqlFactory doesn't yet do the reflection work to return the pre-EF6 NpgsqlServices - Only the 2013 sln is up to date - nuspecs
Tested on: - Windows 7 Home Premium SP1 64-bit - 3 assemblies got into gac. Debug-net45\Npgsql.dll Debug-net45\Npgsql.EntityFramework.dll Legacy-Debug-net45\Npgsql.EntityFrameworkLegacy.dll - machine.config modified. - my EFv6 app's App.config modified.
- Tightened some details in the reflection loading of EntityFrameworkLegacy (thanks kenjiuno) - Did nuspecs entity framework projects - Corrected SLNs for 2012, 2010
OK, I think it's pretty much ready. @kenjiuno, I cherry-picked your commit and added some last fixing. @kenjiuno and @franciscojunior, can I ask you guys for one more checkup, both for the EF6 and legacy EF scenarios? If it all goes well I think we can merge this. |
Rewrote assembly and type resolving better.
Hi. Thanks, I have tested the new code. It raises FileNotFoundException inside NpgsqlFactory.GetService
It seems gac dll needs full qualified typename to be loaded. I have committed quick fix kenjiuno/Npgsql@0265ccd And, I have prepared test toolkit for our easier testing. EdmGen06_20131204.7z https://drive.google.com/file/d/0BzIsP2o582nbZS03Vm9EbmVibjg/edit?usp=sharing EdmGen06 is my alternative one to EdmGen written by MS. It can build schema edmx(ssdl/msl/csdl) files from database (e.g. your PostgreSQL server instance). At that tool, you can try both legacyEF and EFv6 supports, directly. Almost all configurations are already done. for legacyEF
for EFv6
If you succeed, you will get npgsql_tests.edmx. It is useful to be used with code generator such as EF 6.x DbContext Generator. Note: EdmGen06 is still development stage (pre-alpha) Source code: https://github.com/kenjiuno/EdmGen06/releases |
Excellent, Kenji! I think your tool EdmGen06 will be very helpful to Npgsql users :) Shay, sorry I couldn't reply before. I'll make some tests this afternoon and will report you back if I find any problem. |
@kenjiuno, thanks for continuing to work on this. Two things about your proposed commit:
|
Hi.
I agree. I forgot it yesterday ;) I'll consider the possible combinations of .NET and EF, as possible as I can. This is the list of possible ones I think, but I don't check all of them.
Yes, you're right. I had just enjoyed my coding time. ;) sorry. I'll prepare fix. thanks! |
Yes, I don't mind it. |
If you request DbProviderServices, try to load tightly coupled Npgsql.EntityFrameworkLegacy first. And then query NpgsqlServices.TargetProviderServices property. We can know supported version of DbProviderServices by checking TargetProviderServices. We provide NpgsqlServices.Instance if we share same version of EntityFramework library.
Hi. I have changed the approach to Npgsql.EntityFrameworkLegacy. Premise:
Approach:
I have tested on .NET4.5 (legacyEF & EFv6) and .NET3.5 SP1 legacyEF. I hope it should work on user's environment as well. |
I also can confirm the error about the System.Data.Entity assembly not found. I'll also check why it is giving this error. |
After some trial and error this is what I got to make it working: I changed the initial checking of the GetService() to the following:
Would this eliminate the need to load the System.Data.Entity assembly and thus the FileNotFoundException error? After, that, I started to get errors because he couldn't find the Npgsql.EntityFrameworkLegacy assembly. I just had to add the reference to the project in my solution test. After that, the test worked like a charm! Note that I didn't have to add any assembly to the GAC. I tried to get everything using local references. I also only tried the 4.3.1 EF version using the legacy EF. I also noticed that the runtime makes a lot of calls to GetService() method. Maybe it should be a good idea to cache the return of |
I like the approach of looking at the type name rather than loading the assembly, @franciscojunior! It totally circumvents the need to load he entities assembly... And also the idea to cache the type. I will do both now and add a commit. I think kenjiuno is using the GAC because he's using an "external" application (EdmGen). Imagine you have some program using entity frameworks. It doesn't know anything about Npgsql but needs to be able to load the Npgsql EF provider (DbProviderServices). So Npgsql (and also Npgsql.EntityFrameworkLegacy) must be in the GAC... Let me play around and add a commit. |
Great!
I see. I'm using a test program which uses EF. I think he can remove the need to use the GAC if he opens the Npgsql project and adds the edmgen06 as the start program for the project. This way Visual Studio will start edmgen06 using the Npgsql from the project references. @kenjiuno , let me know if you have any problem setting this up. |
I think the point is that a user can't/shouldn't open any projects (neither Npgsql nor edmgen), and doesn't even necessarily have Visual Studio installed to do it... There's still the important question of how a user is supposed to get the Npgsql.dll and NpgsqlEntityFramework.dll DLLs into the GAC, but let's think about that a bit later... |
* Removed #ifdef ENTITIES, which doesn't exist anymore. We have just one Npgsql.dll. * If the user requests legacy EF but didn't install the EntityFrameworkLegacy package/dll, they get an informative exception including the nested exception (is the DLL missing? corrupt?) * If the required members inside Npgsql.EntityFramework.dll can't be found (e.g. Instance) throw an informative exception. This should never happen unless we mess up and release a bad DLL, but still. * Did not understand what the TargetProviderServices property added, so removed for now
Oops, I hadn't seen @kenjiuno's work from before :) OK, I pushed another commit on top of @kenjiuno's work, adding some more informative exceptions and @franciscojunior's proposed caching. @kenjiuno, look at the commit messages, let me know if I missed something for the TargetProviderServices. As far as I understand, the assembly loading itself ensures that we're always using the correct version of Npgsql.EntityFrameworkLegacy (i.e. the same one as Npgsql), so no need for the additional TargetProviderServices mechanism? |
Em 05/12/2013 14:59, "Shay Rojansky" notifications@github.com escreveu:
Agreed. I like to use the project reference because I don't need to change
Yes, I think we should provide some type of installer, or continue to I think the installer would be easier and more practical to the user.
|
Em 05/12/2013 15:33, "Shay Rojansky" notifications@github.com escreveu:
Great! I'll test it when I get back home.
|
@franciscojunior: great. Let's think of both a DDEX VSI installer and an Npgsaql GAC installed as possible features for 2.2! We should also move to github issues at some point, this can be documented there with milestones etc... |
Hello.
No, no worry. you can remove TargetProviderServices safely, now. I understood EFv5 is built on top of legacy EF! I have noticed it today, sorry. I had a minimal test: we can use current Npgsql+Npgsql.EntityFrameworkLegacy on EFv5 as well as legacy EF. EF 5.x DbContext Generator also worked for me. I confirmed it can enumerate entities.
No problem. It can be done, even if it is launch on command prompt directly. Most settings will be done in App.config
Note: I will prepare 3 variants of EdmGen06. [.NET3.5 legacy ef] [.NET4.5 legacy ef] [.NET4.5 EFv6]. Each App.config differs. If we don't use GAC, partially qualified name is accepted. If we have already any Npgsql in GAC... It has to be eliminated at first. This issue will be applied to only our development environment. End users will not concern whether it is installed to GAC or not. However, in some cases, GAC will be still required:
DDEX support doesn't need GAC at all. VisualStudio just calls ADO.net (DbConnection and so on) to query database contents. But there is workaround. Modify DbProviderFactories at runtime. http://stackoverflow.com/questions/1117683/add-a-dbproviderfactory-without-an-app-config @roji thank you for your commit! |
Hi.
It sounds good! And, I have tested the latest commit 086686b. I think I have no more problems on new packaging model of Npgsql, for now. thanks! |
Ok @franciscojunior, as far as we know this is now ok. Do your own testing and let me know whether you're ok with it, feel free to merge... |
Excellent! I also think so.
I agree with you. It would streamline our development process. I'll create a discussion about that in the mailing list. |
So it's OK to merge @franciscojunior? Do you want me to do it? |
Excellent! I'll make some tests and will let you know. But from what you and Kenji said, it seems I won't find any problems and we will be ready to go! :) As soon as I make my tests I'll let you know. And of course I'd like you to make the honor of merging this awesome work :) |
OK. I think it is ready to go. Shay, please, make the honor and merge this pull request. :-)
|
Shay, I don't know if you saw my last message, but I already did some tests here and it worked beautifully! Ready to merge! |
Entity framework work for release 2.1.0
Sweet! Awesome, Shay! This will help our users get better and faster Npgsql releases! |
This is still WIP, please do not merge.
Continued discussion from #109 (comment)