Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Conversation

@kenjiuno
Copy link
Contributor

SqlFunctionGenerator appended:

  • PostgreSQL's Functions/StoredProcedures can be called through EntityFramework's ObjectContext.ExecuteFunction by this change.
  • Currently we get ArgumentException because NpgsqlServices.TranslateCommandTree doesn't support DbFunctionCommandTree as an input.

Changes for NpgsqlSchema.ssdl

  • I appended missing Association/AssociationSet elements in ssdl. They tell table's relationship defined in PostgreSQL, to EF.
  • This fix will be useful, when you write your own EdmGen tool.

Changes for NpgsqlSchema.msl

  • I fixed a potential problem.
  • This fix will be useful, when you write your own EdmGen tool.

@kenjiuno
Copy link
Contributor Author

Here is the long long detailed procedures to test my fix.

Prepare a PostgreSQL instance for ready to use.

Assuming,

  • PostgreSQL 9.3.1, Windows, 64-bit
  • Host: 127.0.0.1
  • Port: 5432
  • User: riceu
  • Pass: riceu
  • Database: rice
  • Schema: public

Create a function.

Example:

-- Function: passthru(text)

-- DROP FUNCTION passthru(text);

CREATE OR REPLACE FUNCTION passthru(p text)
RETURNS text AS
'select p::text;'
LANGUAGE sql STABLE
COST 100;
ALTER FUNCTION passthru(text)
OWNER TO postgres;
GRANT EXECUTE ON FUNCTION passthru(text) TO public;
GRANT EXECUTE ON FUNCTION passthru(text) TO postgres;
GRANT EXECUTE ON FUNCTION passthru(text) TO riceu;

Build your Npgsql

Open Npgsql2012.sln with VS2012 Express for Desktop.

Select configuration Release-net45

Build Npgsql

Register your Npgsql and dependent assembly into GAC

gacutil /i Npgsql.dll
gacutil /i Mono.Security.dll

Check your installed assembly signature.

gacutil /l Npgsql
The Global Assembly Cache contains the following assemblies:
  Npgsql, Version=2.0.12.91, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7, processorArchitecture=MSIL

Number of items = 1

Edit machine.config

C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config

Add new element to DbProviderFactories.

      <add 
        name="Npgsql Data Provider" 
        invariant="Npgsql" 
        support="FF" 
        description=".Net Framework Data Provider for PostgreSQL Server" 
        type="Npgsql.NpgsqlFactory, Npgsql, Version=2.0.12.91, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7" />

New C# project

Launch VS2012 Express for Desktop.

New Project
Visual C#
Console Application

ConsoleApplication7

Invoke EdmGen

Launch Command Prompt.

Move your current directory to ConsoleApplication7.

Invoke EdmGen then.

C:\Windows\Microsoft.NET\Framework\v4.0.30319\EdmGen.exe /mode:FullGeneration /project:ConsoleApplication7 /provider:Npgsql /c:"Port=5432;Encoding=UTF-8;Server=127.0.0.1;Database=rice;UserId=riceu;Password=riceu;Preload Reader=true;" /targetversion:4.5

Output sample:

EdmGen for Microsoft (R) .NET Framework version 4.5
Copyright (C) Microsoft Corporation. All rights reserved.

Loading database information...
warning 6013: The table/view 'rice.public.VOrder' does not have a primary key defined and no valid primary key could be inferred. This table/view has been excluded. To use the entity, you will need to review your schema, add the correct keys, and uncomment it.
Writing ssdl file...
Creating conceptual layer from storage layer...
Writing msl file...
Writing csdl file...
Writing object layer file...
Writing views file...

Generation Complete -- 0 errors, 1 warnings

Edit ssdl

Open ConsoleApplication7.ssdl

Edit Function passthru.

  <Function Name="passthru" StoreFunctionName="passthru" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="public" BuiltIn="false" NiladicFunction="false" Aggregate="false">
    <Parameter Name="p" Mode="In" Type="text" />
  </Function>

Replace "ConsoleApplication7.Store" with "public".

Save it.

Edit msl

Open ConsoleApplication7.msl

Add FunctionImportMapping.

<Mapping ...>
  <EntityContainerMapping ...>
    ...
    <FunctionImportMapping FunctionImportName="passthru" FunctionName="public.passthru" />
  </EntityContainerMapping>
</Mapping>

Save it.

Edit csdl

Open ConsoleApplication7.csdl

Add FunctionImport

<Schema ...>
  <EntityContainer ...>
    ...
    <FunctionImport Name="passthru" ReturnType="Collection(String)">
      <Parameter Name="p" Mode="In" Type="String" />
    </FunctionImport>
  </EntityContainer>
  <EntityType ...>
    ...
  </EntityType>
</Schema>

Make sure you add FunctionImport into EntityContainer, not EntityType.

Save it.

Generate new object layer by EdmGen

Invoke EdmGen.

C:\Windows\Microsoft.NET\Framework\v4.0.30319\EdmGen.exe /mode:EntityClassGeneration /incsdl:ConsoleApplication7.csdl /project:ConsoleApplication7 /targetversion:4.5
EdmGen for Microsoft (R) .NET Framework version 4.5
Copyright (C) Microsoft Corporation. All rights reserved.

Writing object layer file...

Generation Complete -- 0 errors, 0 warnings

Add assembly references

Add reference to

System.Data.Entity
System.Runtime.Serialization

Add object layer

Add the file to your C# project

ConsoleApplication7.ObjectLayer.cs

Add schema files

Add your schema files into your project.

ConsoleApplication7.csdl
ConsoleApplication7.msl
ConsoleApplication7.ssdl

Copy your schema files into bin dir.

About 3 files, set "Copy to Output Directory" property to "Copy if newer".

Edit App.config

Add your connectionString into App.config

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
    <!--for EF4.x (NET4.0/NET4.5)-->
    <add name="ConsoleApplication7Context" connectionString="metadata=ConsoleApplication7.csdl|ConsoleApplication7.ssdl|ConsoleApplication7.msl;provider=Npgsql;provider connection string=&quot;Port=5432;Encoding=UTF-8;Server=127.0.0.1;Database=rice;UserId=riceu;Password=riceu;Preload Reader=true;&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
</configuration>

Edit Program.cs

Make sure to call function passthru.

using System;

namespace ConsoleApplication7
{
    class Program
    {
        static void Main(string[] args)
        {
            var Context = new ConsoleApplication7Context();
            foreach (var res in Context.passthru("Hello from entity framework powered by Npgsql!"))
            {
                Console.WriteLine(res);
            }
        }
    }
}

Run your application

The following result is brought if everything goes well.

Hello from entity framework powered by Npgsql!
Press any key to continue . . .

You may get ArgumentException within EntityCommandCompilationException, if your Npgsql doesn't have DbFunctionCommandTree support.

Unhandled Exception: System.Data.EntityCommandCompilationException: An error occurred while preparing the command definition. See the inner exception for details. ---> System.ArgumentException: Value does not fall within the expected range.
   at Npgsql.NpgsqlServices.TranslateCommandTree(DbCommandTree commandTree, DbCommand command)
   at Npgsql.NpgsqlServices.CreateDbCommand(DbCommandTree commandTree)
...

Otherwise you might get other exception messages.

@franciscojunior
Copy link
Member

That's awesome, Kenji!

If you don't mind, I'll later create add your instructions to our User Manual so others can benefit from your instructions. Thank you very much!

@kenjiuno
Copy link
Contributor Author

Hi.

I don't mind the usage of procedures. I'll help you, for example, if you need more detailed explanation.

thanks

@franciscojunior
Copy link
Member

I just tested it and it worked like a charm! I used VS2013 though because I had a problem with VS2012 after I installed VS2013. But I think the update 4 for VS2012 will fix this problem and I'll test it in VS2012 too.

One question: why is needed to make those changes to generated files? Is Npgsql support missing to get those files correctly built? Or are those changes also needed when working with SQL Server? (I don't have much experience with Entity Framework with SQL Server)

Other than that, I think those changes are very good. Excellent work, Kenji Uno! Thank you very much!

I don't mind the usage of procedures. I'll help you, for example, if you need more detailed explanation.

thanks

I'll add your documentation to our user manual. Thank you too for your contributions!

@kenjiuno
Copy link
Contributor Author

Hi.

One question: why is needed to make those changes to generated files? Is Npgsql support missing to get those files correctly built? Or are those changes also needed when working with SQL Server? (I don't have much experience with Entity Framework with SQL Server)

It'll be implementation issue of EdmGen (and also VS Designer support).

We can get same result with SQL Server provider. I've confirmed it a hour ago.

Perhaps my problem may be insignificant one.

Many people won't feel so much difficulty, because they don't need to use StoredProcedures/Functions through EF support.

We can easily call StoredProcedures/Functions by invoking NpgsqlCommand.

I'm lazy man. So I wrote EdmGen06. It can generate schema files with StoredProcedures/Functions generation support.

The fix of NpgsqlSchema.ssdl and NpgsqlSchema.msl was needed to complete EdmGen06.

thanks
kenji uno

@franciscojunior
Copy link
Member

Excellent!

When possible, please, add an example using your tool so we can add it to our user manual.

@franciscojunior
Copy link
Member

Another comment:

You have a class called Eut in SqlFunctionGenerator which has a single method called escape which just returns the parameter. Is this intended? Would it be possible to just use the parameter directly?

Would it be possible for you to squash or remove the first commit? It is empty! (I don't know how you could get git to do that in first place :) ) Thanks in advance.

@kenjiuno
Copy link
Contributor Author

Hi.

You have a class called Eut in SqlFunctionGenerator which has a single method called escape which just returns the parameter. Is this intended? Would it be possible to just use the parameter directly?

Thanks. It forgot I have placed EUt.

I have tested if we can call upper-case-first function like public.PassThrough without quote marks. It couldn't.

So I will add some codes for quote marks like "public"."PassThrough".

Would it be possible for you to squash or remove the first commit? It is empty! (I don't know how you could get git to do that in first place :) ) Thanks in advance.

Ok :)

When possible, please, add an example using your tool so we can add it to our user manual.

Ok!

kenjiuno and others added 2 commits November 28, 2013 23:05
Fixed EndProperty names in msl's ViewConstraintColumns.
Appended missing Association/AssociationSet in ssdl.
Added experimental SqlFunctionGenerator for EF Function call support.
@kenjiuno
Copy link
Contributor Author

Hi.

I have pushed a new commit, that is produced by TortoiseGit's Combine to one commit, with force push option.

About EUt, I have replaced with SqlBaseGenerator.QuoteIdentifier that is already used in other EF support codes.

I'll write example with: ef_code_first_sample as ef_db_first_sample :)

http://fxjr.blogspot.jp/2013/06/npgsql-code-first-entity-framework-431.html

@franciscojunior
Copy link
Member

Hi.

I have pushed a new commit, that is produced by TortoiseGit's Combine to one commit, with force push option.

Great!

About EUt, I have replaced with SqlBaseGenerator.QuoteIdentifier that is already used in other EF support codes.

Excellent! I'll check it.

I'll write example with: ef_code_first_sample as ef_db_first_sample :)

http://fxjr.blogspot.jp/2013/06/npgsql-code-first-entity-framework-431.html

:)

I'm looking forward it.

@kenjiuno
Copy link
Contributor Author

ef_db_first_sample instruction

Tested on:

  • Windows 8.1 Pro with Media Center x64
  • PostgreSQL 9.3.1, compiled by Visual C++ build 1600, 64-bit

Create a database

With command line:

createdb ef_db_first_sample 

If you can invoke SQL commands, try:

CREATE DATABASE ef_db_first_sample
  WITH ENCODING='UTF8'
       TEMPLATE=template0
       LC_COLLATE='C'
       LC_CTYPE='C'
       CONNECTION LIMIT=-1;

Add role "npgsql_tests" with pass "npgsql_tests"

Invoke SQL commands:

CREATE ROLE npgsql_tests LOGIN
  PASSWORD 'npgsql_tests'
  NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION;

Create sample tables: Blog and Post

Invoke SQL commands:

CREATE TABLE "Blog"
(
  "BlogId" serial NOT NULL,
  "Name" character varying(255),
  CONSTRAINT "Blog_pkey" PRIMARY KEY ("BlogId")
);

CREATE TABLE "Post"
(
  "PostId" serial NOT NULL,
  "Title" character varying(255),
  "Content" character varying(8000),
  "BlogId" integer,
  CONSTRAINT "Post_pkey" PRIMARY KEY ("PostId"),
  CONSTRAINT "Post_BlogId_fkey" FOREIGN KEY ("BlogId")
      REFERENCES "Blog" ("BlogId") MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
);

Grant permissions to role npgsql_tests:

GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE "Blog" TO npgsql_tests;
GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE "Post" TO npgsql_tests;

GRANT SELECT, UPDATE ON TABLE "Blog_BlogId_seq" TO npgsql_tests;
GRANT SELECT, UPDATE ON TABLE "Post_PostId_seq" TO npgsql_tests;

Generate an edmx file from your database

EdmGen06 is a partially compatible tool to Microsoft's EdmGen.

The latest binary releases will be available at https://github.com/kenjiuno/EdmGen06/wiki

Extract the files somewhere.

Launch command prompt.

Enter EFv4 directory.

Try next command.

EdmGen06 ^
  /ModelGen ^
  "Port=5432;Encoding=UTF-8;Server=127.0.0.1;Database=ef_db_first_sample;UserId=npgsql_tests;Password=npgsql_tests;Preload Reader=true;" ^
  "Npgsql" ^
  "Blogging" ^
  "public" ^
  "3.0"

You will see output like following lines:

EdmGen06 Information: 101 : ModelGen v3
EdmGen06 Information: 101 : Getting System.Data.Common.DbProviderFactory from 'Npgsql'
EdmGen06 Information: 101 : Npgsql.NpgsqlFactory, Npgsql, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7
EdmGen06 Information: 101 : file:///H:/Dev/EdmGen06/test/EFv4/Npgsql.DLL
EdmGen06 Information: 101 : Ok
EdmGen06 Information: 101 : Connecting
EdmGen06 Information: 101 : Connected
EdmGen06 Information: 101 : Getting System.Data.Common.DbProviderServices from 'Npgsql'
EdmGen06 Information: 101 :  from IServiceProvider.GetService method
EdmGen06 Information: 101 : Npgsql.NpgsqlServices, Npgsql.EntityFrameworkLegacy, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7
EdmGen06 Information: 101 : file:///H:/Dev/EdmGen06/test/EFv4/Npgsql.EntityFrameworkLegacy.DLL
EdmGen06 Information: 101 : Ok
EdmGen06 Information: 101 : Get ProviderManifestToken
EdmGen06 Information: 101 : Get ProviderManifest
EdmGen06 Information: 101 : Get StoreSchemaDefinition
EdmGen06 Information: 101 : Get StoreSchemaMapping
EdmGen06 Information: 101 : Write temporary ProviderManifest ssdl
EdmGen06 Information: 101 : Write temporary ProviderManifest msl
EdmGen06 Information: 101 : Checking ProviderManifest version.
EdmGen06 Information: 101 : ProviderManifest v1
EdmGen06 Information: 101 : Write temporary ProviderManifest csdl
EdmGen06 Information: 101 : Getting SchemaInformation
EdmGen06 Information: 101 : Ok
EdmGen06 Information: 101 : Table: public.Blog
EdmGen06 Information: 101 :  TableColumn: BlogId
EdmGen06 Information: 101 :  TableColumn: Name
EdmGen06 Information: 101 : Table: public.Post
EdmGen06 Information: 101 :  TableColumn: PostId
EdmGen06 Information: 101 :  TableColumn: Title
EdmGen06 Information: 101 :  TableColumn: Content
EdmGen06 Information: 101 :  TableColumn: BlogId
EdmGen06 Information: 101 : Constraint: Post_BlogId_fkey

Blogging.App.config

Open "Blogging.App.config" generated by EdmGen06.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <!--configSections has to be FIRST element!-->
  <configSections>
    <!--for EF6.0.x -->
    <!--you don't need this. your nuget will setup automatically-->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <system.data>
    <DbProviderFactories>
      <!--for EF4.x and EF6.0.x -->
      <!--you may need this. if you don't modify machine.config-->
      <remove invariant="Npgsql" />
      <add name="Npgsql - .Net Data Provider for PostgreSQL" invariant="Npgsql" description=".Net Data Provider for PostgreSQL" type="Npgsql.NpgsqlFactory, Npgsql, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7" />
    </DbProviderFactories>
  </system.data>
  <connectionStrings>
    <!--for EF4.x and EF6.0.x -->
    <add name="BloggingEntities" connectionString="metadata=Blogging.csdl|Blogging.ssdl|Blogging.msl;provider=Npgsql;provider connection string=&quot;Port=5432;Encoding=UTF-8;Server=127.0.0.1;Database=ef_db_first_sample;UserId=npgsql_tests;Password=npgsql_tests;Preload Reader=true;&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
  <entityFramework>
    <providers>
      <!--for EF6.0.x -->
      <!--you need this. add it manually-->
      <provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, Npgsql.EntityFrameworkLegacy, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7" />
    </providers>
  </entityFramework>
</configuration>

Take the element and its children: <system.data>
Take the element and its children: <connectionStrings>

Create an application with VisualStudio2012ExpressForDesktop

Template: Console Application (C#)
Name: DBFirstNewDatabaseSample

Edit your App.config

  1. Add the elements: <system.data>
  2. Add the elements: <connectionStrings>

Your App.config will look like:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <system.data>
    <DbProviderFactories>
      <!--for EF4.x and EF6.0.x -->
      <!--you may need this. if you don't modify machine.config-->
      <remove invariant="Npgsql" />
      <add name="Npgsql - .Net Data Provider for PostgreSQL" invariant="Npgsql" description=".Net Data Provider for PostgreSQL" type="Npgsql.NpgsqlFactory, Npgsql, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7" />
    </DbProviderFactories>
  </system.data>
  <connectionStrings>
    <!--for EF4.x and EF6.0.x -->
    <add name="BloggingEntities" connectionString="metadata=Blogging.csdl|Blogging.ssdl|Blogging.msl;provider=Npgsql;provider connection string=&quot;Port=5432;Encoding=UTF-8;Server=127.0.0.1;Database=ef_db_first_sample;UserId=npgsql_tests;Password=npgsql_tests;Preload Reader=true;&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
</configuration>

Add Blogging.edmx

Add "Blogging.edmx" generated by EdmGen06, to your project.

Edit the property of Blogging.edmx

Custom tool: EntityModelCodeGenerator
Build action: EntityDeploy

Copy Npgsql.dll and Npgsql.EntityFrameworkLegacy.dll

Copy "Npgsql.dll" and "Npgsql.EntityFrameworkLegacy.dll" files into your project folder.

Edit the property:

  • Set "Copy to Output Directory" to "Copy if newer".

Reading & Writing Data

Edit your Program.cs

using System;
using System.Linq;

namespace DBFirstNewDatabaseSample {
    class Program {
        static void Main(string[] args) {
            using (var db = new BloggingEntities()) {
                // Create and save a new Blog
                Console.Write("Enter a name for a new Blog: ");
                var name = Console.ReadLine();

                var blog = new Blog { Name = name };
                db.Blog.AddObject(blog);
                db.SaveChanges();

                // Display all Blogs from the database
                var query = from b in db.Blog
                            orderby b.Name
                            select b;

                Console.WriteLine("All blogs in the database:");
                foreach (var item in query) {
                    Console.WriteLine(item.Name);
                }

                Console.WriteLine("Press any key to exit...");
                Console.ReadKey();
            }
        }
    }
}

Launch, and enjoy it!

Enter a name for a new Blog: my first blog
All blogs in the database:
my first blog
Press any key to exit...

@franciscojunior
Copy link
Member

Awesome, Kenji! I'll create some wiki pages with your documentation. Thank you very much!

@franciscojunior
Copy link
Member

Just started to create the Npgsql user manual wiki page and I added your ef_db_first sample: https://github.com/npgsql/Npgsql/wiki/User-Manual#ef_db_first_sample-instruction

Thank you for creating this explanation, Kenji! It will help many Npgsql users.

@roji
Copy link
Member

roji commented Dec 11, 2013

Small suggestion: since there's lots of stuff in the manual and EF doesn't necessarily interest everyone, maybe a separate wiki page on EF?

@franciscojunior
Copy link
Member

Small suggestion: since there's lots of stuff in the manual and EF doesn't necessarily interest everyone, maybe a separate wiki page on EF?

I thought about that but in the opposite direction. :)
At first I thought about creating a page only with EF data and include this sample. After some time I thought it would be better to have everything together and then I started to create the document with all info.

But I think we can try another approach: Create another wiki page specifically to EF ( and later create one for DDEX and any other macro topic) and add a link to them in the User Manual.

What do you all think?

@roji
Copy link
Member

roji commented Dec 11, 2013

Sounds great to me!

We can split off any subject into its own page and have links to make things clearer...

Note that the wiki has a "Root" page, which is what you see when you click on "Wiki" in github. I've already placed links there to some stuff, feel free to organize as you see fit...

@franciscojunior
Copy link
Member

Great!

Yes, I saw you placed some links there. I'll make the changes...

@kenjiuno
Copy link
Contributor Author

Thank for you update the wiki!

@franciscojunior
Copy link
Member

Thank for you update the wiki!

You are welcome!
I'll add more information based on your posts and on Npgsql Manual.
Thank you too for all your help.

@roji
Copy link
Member

roji commented Dec 16, 2013

Superceded by #129

@roji roji closed this Dec 16, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.