Showstopper: EF query translation and ProviderManifestToken

Discussion of open issues, suggestions and bugs regarding ADO.NET provider for Oracle
Post Reply
Dennis Wanke
Posts: 57
Joined: Tue 11 Mar 2014 07:49

Showstopper: EF query translation and ProviderManifestToken

Post by Dennis Wanke » Mon 12 May 2014 09:06

Currently, as an Entity Framework query gets translated by dotConnect (either an ESQL or a LINQ one), its "dialect" depends on the value of the ProviderManifestToken attribute from SSDL schema.
This behavior makes it impossible to use the same SSDL schema against multiple server versions (e.g. 11g and 12c).
Desired behavior would be to perform query translation based on a real version of the server in use (i.e. of the one, to which a connection is going to be established). This can be done for instance using ProviderManifestToken returned by DbProviderServices.GetProviderManifestToken(connection).

Shalex
Site Admin
Posts: 9543
Joined: Thu 14 Aug 2008 12:44

Re: Showstopper: EF query translation and ProviderManifestToken

Post by Shalex » Wed 21 May 2014 15:42

This is how Entity Framework works in case of XML mapping (edmx/edml files).
ProviderManifestToken stores all needed information about the target server so that Entity Framework engine be able to create SQL in the disconnected mode without "live" connection to the database. Here is a workaround: set Metadata Artifact Processing=Copy To Output Directory for your model to generate separate mapping files (*.csdl, *.ssdl, *.msl) and use the following code:

Code: Select all

    using (var conn = new OracleConnection("User Id=scott;Password=tiger;Server=orcl1120;")) {
        conn.Open();
                
        XmlDocument xmlDoc = new XmlDocument();
        if (File.Exists("DataModel1.ssdl")) {
            xmlDoc.Load("DataModel1.ssdl");
        }
        else {
            throw new FileNotFoundException("DataModel1.ssdl doesn't exist");
        }
        XmlNode schemaNode = xmlDoc["Schema"];
        XmlAttribute providerManifestTokenAttribute = schemaNode.Attributes["ProviderManifestToken"];
        // set new value of ProviderManifestToken
        providerManifestTokenAttribute.Value = "Oracle, " + conn.ShortServerVersion.ToString();
        // create new *.ssdl
        xmlDoc.Save("DataModel1_NEWLYCREATED.ssdl");

    }

    // initialize context with newly added ProviderManifestToken
    using(SCOTTModel.SCOTTEntities context = new SCOTTModel.SCOTTEntities()){
        context.Connection.ConnectionString = "metadata=.\\DataModel1.csdl|.\\DataModel1_NEWLYCREATED.ssdl|.\\DataModel1.msl;provider=Devart.Data.Oracle;provider connection string=\"User Id=scott;Password=tiger;Server=orcl1120;Persist Security Info=True\"";
        context.Connection.Open();
        var depts = context.DEPTs.ToList();
    }
In fact ProviderManifestToken is determined via DbProviderServices.GetProviderManifestToken(connection) "on the fly" by Entity Framework in the Code-First approach which uses attribute/fluent mapping.

Post Reply