Search found 25 matches

by Remco Blok
Fri 24 Aug 2012 09:58
Forum: Entity Framework support
Topic: Generated sql for Linq Any method
Replies: 8
Views: 2816

Re: Generated sql for Linq Any method

Hi Shalex,

I had not responded to this earlier to thank you for the fix, because I thought it was only partially fixed. I saw the CASE generation was improved but there were still duplicated left outer joins. However, I noticed that with .NET 4.5 the duplicated left outer join issue is resolved as well. So that issue must have been in the core Entity Framework code in the .NET Framework (and I mean the core EF code, not the EF NuGet package), rather than in the Devart provider.

many thanks

Remco
by Remco Blok
Fri 24 Aug 2012 08:42
Forum: Entity Framework support
Topic: .NET 4.5 compatibility heads up
Replies: 5
Views: 2522

.NET 4.5 compatibility heads up

All,

Just a heads up on .NET 4.5 compatibility. I installed .NET 4.5 on my development PC. However, my application targets .NET 4.0. As you may know .NET 4.5 is an in-place upgrade of .NET 4.0, rather than a side-by-side installation. So if you have .NET 4.5 installed, but you are targeting .NET 4.0, at runtime you will be running .NET 4.5. Turns out that the core Entity Framework code in .NET 4.5 generates different sql than .NET 4.0. Note that I am talking about the core Entity Framework code in the .NET Framework, not about the Entity Framework NuGet package. I found out about the different sql that was generated when I deployed the code to a test server that did not have .NET 4.5 installed.

The generated sql actually failed to parse on the test database. The development database had some new fields added to tables, that were not yet deployed to the test database. The EF model was updated from the development database (database-first is used). The LINQ code though did not select from any of those new fields so I expected it would run fine on the older test database. Well, you know how the generated sql sometimes contains inline select statements that select all the fields from a table when the outer select statements picks only the ones you asked for? That's why the sql did not parse on the test database because the inline select statement was selecting from all the fields the EF model knew about, but some of those fields were not yet deployed on the test database.

The sql on my developer PC was different. On my developer pc the inner select statement only selects those fields that are needed by the outer select statement (or where clauses etc). Much better sql, but I could not understand why it was different. At first I thought a different version of Devart dotConnect for Oracle was deployed on the test server. I made sure they were the same version. Turns out the generated sql on my developer PC was different because I had .NET 4.5 installed. Sure, .NET 4.5 generates better sql than .NET 4.0. But when you target .NET 4.0 you expect it to use .NET 4.0. Why o why is .NET 4.5 an in-place upgrade???

For my test server there were in fact two solutions now: either deploy the latest version of the database, or install .NET 4.5. Of course the correct solution was to deploy the latest version of the database to the test server. Perhaps I should also remove .NET 4.5 from my developer PC while I'm still targeting .NET 4.0.

Remco
by Remco Blok
Wed 20 Jun 2012 12:38
Forum: Entity Framework support
Topic: Migrations: identifier name length
Replies: 12
Views: 3547

Re: Migrations: identifier name length

Hi Shalex, Apologies, I seem to have missed the notification of your further reply to this post.

I don't think I would want the identifiers simply truncated if that's only going to give potential conflicts due to non-uniqueness.

Since I don't care about the identifier name of indices and foreign keys at all, I was really hoping the provider could generate some random unique name, and store this in the metadata of the model so that it can compare the version in the database with the version of the model. But I can imagine that may be quite tricky.

The problem with being forced to do a code-based migration because of the identifier name of indices and foreign keys being over 30 chars is that the code based migration then specifies everything in code. For instance for a new table the migration now contains the CreateTable and PrimaryKey statements when I only want the migration to explicitly specify the name of a foreign key or index. So if I could specify the name of foreign keys and indices by decorating (navigation)properties on my entity classes, then perhaps I can do an automatic migration again.
by Remco Blok
Mon 11 Jun 2012 14:32
Forum: dotConnect for Oracle
Topic: ChangeDatabase, EntityFramework and ASP.NET Providers
Replies: 5
Views: 1920

Re: ChangeDatabase, EntityFramework and ASP.NET Providers

never mind. The following connection string works for me (using OS Authentication):

Server=localhost;Sid=XE;Initialization Command=ALTER SESSION SET CURRENT_SCHEMA=MYSCHEMA

Thanks very much. Works very well!
by Remco Blok
Mon 11 Jun 2012 14:13
Forum: dotConnect for Oracle
Topic: ChangeDatabase, EntityFramework and ASP.NET Providers
Replies: 5
Views: 1920

Re: ChangeDatabase, EntityFramework and ASP.NET Providers

Hi Shalex,

Thanks for the quick response. Could you clarify how to use this initialization command in the connection string. The command I would like to execute is like ALTER SESSION SET CURRENT_SCHEMA = MYSCHEMA.

many thanks

Remco
by Remco Blok
Tue 29 May 2012 17:14
Forum: Entity Framework support
Topic: Migration to 11.2 ok, 10.2 gives ORA-06550
Replies: 1
Views: 1224

Migration to 11.2 ok, 10.2 gives ORA-06550

Hello,

When I apply my EF Code First Migrations to an Oracle 11.2 database everything goes fine. When I apply the same migrations to an Oracle 10.2 database I get the following error at the point when the migration tries to insert a record with a large blob into the __MigrationHistory table. Can you help please?

thanks

Remco

Devart.Data.Oracle.OracleException (0x80004005): ORA-06550: line 8, column 5:
PLS-00103: Encountered the symbol "" The symbol "" was ignored.
at Devart.Data.Oracle.t.d()
at Devart.Data.Oracle.at.h()
at Devart.Data.Oracle.at.c()
at Devart.Data.Oracle.aa.a(Int32 A_0, bw A_1)
at Devart.Data.Oracle.OracleCommand.InternalExecute(CommandBehavior behavior, IDisposable disposable, Int32 startRecord, Int32 maxRecords, Boolean nonQuery)
at Devart.Common.DbCommandBase.ExecuteDbDataReader(CommandBehavior behavior, Boolean nonQuery)
at Devart.Data.Oracle.OracleCommand.ExecuteNonQuery()
at System.Data.Entity.Migrations.DbMigrator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements)
at System.Data.Entity.Migrations.Infrastructure.MigratorBase.ExecuteStatements(IEnumerable`1 migrationStatements)
at System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, XDocument targetModel, IEnumerable`1 operations, Boolean downgrading)
at System.Data.Entity.Migrations.DbMigrator.ApplyMigration(DbMigration migration, DbMigration lastMigration)
at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ApplyMigration(DbMigration migration, DbMigration lastMigration)
at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.RunCore()
at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run()
ORA-06550: line 8, column 5:
PLS-00103: Encountered the symbol "" The symbol "" was ignored.
by Remco Blok
Fri 18 May 2012 09:31
Forum: Entity Framework support
Topic: Migrations: identifier name length
Replies: 12
Views: 3547

Migrations: identifier name length

Hello,

My app targets either Microsoft SQL Server or Oracle depending on the connection string. All code is supposed to be database agnostic. I try to use automatic migrations where possible. I find that most migrations can work automatically when targeting MS SQL Server. But the same automatic migration cannot be applied when targeting Oracle because the generated identifier names of foreign keys and indices are too long. Now for the sake of Oracle I have to do code-based migrations to explicitly name those identifiers where SQL Server was happy with the generated identifiers and automatic migrations. I must say I don't care too much about the names of foreign keys and indices and having to explicitly name them for Oracle only is a pain. It's great that Devart has validation on the identifier name length to prevent the migration from even starting, but it would be better if the convention for generating names for foreign keys and indices could be changed so that migrations can be done automatically again. Is this something that can be done in Devart's provider, or is this naming convention part of core EntityFramework that cannot be changed by Devart?

Remco
by Remco Blok
Thu 17 May 2012 09:31
Forum: dotConnect for Oracle
Topic: ChangeDatabase, EntityFramework and ASP.NET Providers
Replies: 5
Views: 1920

ChangeDatabase, EntityFramework and ASP.NET Providers

Hello,

I use dotConnect for Oracle for my EntityFramework DbContext and I also use the ASP.NET providers. I like to connect to Oracle as one user and then work with the objects in another schema. It was great that Devart implemented the ChangeDatabase method on the OracleConnection class.

When using EntityFramework, I can change schema by writing a custom IDbConnectionFactory as follows:

Code: Select all

    public class OracleConnectionFactory : IDbConnectionFactory
    {
        private readonly string baseConnectionString;
        private readonly IDictionary<DbConnection, string> connections = new Dictionary<DbConnection, string>();
        private Func<string, DbProviderFactory> providerFactoryCreator;

        public OracleConnectionFactory()
        {
            this.baseConnectionString = "Server=localhost;Sid=XE";
        }

        public OracleConnectionFactory(string baseConnectionString)
        {
            Contract.Requires(baseConnectionString != null);
            this.baseConnectionString = baseConnectionString;
        }

        public string BaseConnectionString
        {
            get
            {
                return this.baseConnectionString;
            }
        }

        internal Func<string, DbProviderFactory> ProviderFactory
        {
            get
            {
                if (this.providerFactoryCreator == null)
                {
                    this.providerFactoryCreator = DbProviderFactories.GetFactory;
                }

                return this.providerFactoryCreator;
            }

            set
            {
                this.providerFactoryCreator = value;
            }
        }

        public DbConnection CreateConnection(string nameOrConnectionString)
        {
            Contract.Assume(!string.IsNullOrWhiteSpace(nameOrConnectionString));

            var connectionString = nameOrConnectionString;
            var name = string.Empty;

            if (nameOrConnectionString.IndexOf('=') == -1)
            {
                connectionString = new OracleConnectionStringBuilder(this.baseConnectionString).ConnectionString;
                name = nameOrConnectionString.ToUpperInvariant();
                var index = name.LastIndexOf('.');
                if (index != -1)
                {
                    var startIndex = index + 1;
                    name = name.Substring(startIndex, name.Length - startIndex);
                }
            }

            DbConnection connection;
            try
            {
                connection = this.ProviderFactory("Devart.Data.Oracle").CreateConnection();
                connection.ConnectionString = connectionString;
            }
            catch
            {
                connection = new OracleConnection(connectionString);
            }

            if (!string.IsNullOrEmpty(name))
            {
                connection.Disposed += this.OnConnectionDisposed;
                connection.StateChange += this.OnConnectionStateChange;

                this.connections.Add(connection, name);
            }

            return connection;
        }

        private void OnConnectionDisposed(object sender, EventArgs e)
        {
            var connection = (DbConnection)sender;
            connection.Disposed -= this.OnConnectionDisposed;
            connection.StateChange -= this.OnConnectionStateChange;
            this.connections.Remove(connection);
        }

        private void OnConnectionStateChange(object sender, StateChangeEventArgs e)
        {
            if (e.CurrentState == ConnectionState.Open)
            {
                var connection = (DbConnection)sender;
                string name;
                if (this.connections.TryGetValue(connection, out name))
                {
                    connection.ChangeDatabase(name);
                }
            }
        }
    }
This connection factory will only change schema if the nameOrConnectionString parameter represents a name, not a connection string. So, in my web/app.config I configure this connection factory with a base connection string in the entityframework/defaultConnectionFactory element, but I do not add a connection string to the connectionStrings element, otherwise the nameOrConnectionString parameter represents a connection string, not a name.

I choose to use a connection factory, because I did not want to polute every place where I create a DbContext with additional code to explicitly create an OracleConnection and handle the StateChange event as per Devart's blog post here: http://blogs.devart.com/dotconnect/enti ... qlite.html.

More important though is that my code must be database agnostic. Simply by changing the connection string users must be able to use Microsoft SQL Server, or Oracle.

So using a connection factory works fine. But I can imagine a scenario where you might have two EntityFramework DbContexts for different databases. Using this connection factory only works if both databases are Oracle and share the same base connection string.

I also use Devart's ASP.NET providers for Membership and Profile. Again, I would like to connect to Oracle as one user and then work with the objects in another schema.

I think to get that to work I would have to derive from Devart's OracleProviderFactory and override its CreateConnection method so that I can handle the StateChange event to change to another schema. But how can I specify which schema? I think the only way to do this is to add a custom connection string property. I will then have to derive from OracleConnectionStringBuilder and derive from OracleConnection. Could Devart provide guidance on how I go about that? I see the OracleConnection class exposes an internal ConnectionOptions property. Being internal I cannot change these ConnectionOptions. So it would be best if Devart could add support for this schema property in the connection string. I will then no longer need my EntityFramework connection factory either.

Remco
by Remco Blok
Mon 09 Apr 2012 08:45
Forum: Entity Framework support
Topic: Generated sql for Linq Any method
Replies: 8
Views: 2816

Hi Devart,

Thans for improving the sql for the Any method. I came accross another scenario that produces similar sql. Say you have the following linq statement:

from user in this.Context.Users
select user.SomeProperty == "Y"

That would result in sql like:

SELECT
CASE WHEN "Extent1".SOME_PROPERTY = 'Y' THEN 1 WHEN "Extent1".SOME_PROPERTY 'Y' THEN 0 END AS C1
FROM USERS "Extent1"

I suppose this could be better written as:

SELECT
CASE WHEN "Extent1".SOME_PROPERTY = 'Y' THEN 1 ELSE 0 END AS C1
FROM USERS "Extent1"

I also came accross the following strange scenario. This time I query a navigation property of a 1 to 0 or 1 relationship:

from user in this.Context.Users
select user.Action == null

This produces the following sql:

SELECT
CASE WHEN "Extent3".USER_ID IS NULL THEN 1 ELSE 0 END AS C1
FROM USERS "Extent1"
LEFT OUTER JOIN USER_ACTION "Extent2" ON "Extent1".USER_ID = "Extent2".USER_ID
LEFT OUTER JOIN USER_ACTION "Extent3" ON "Extent2".USER_ID = "Extent3".USER_ID

Why does it generate the same left outer join twice? The sql should really have been:

SELECT
CASE WHEN "Extent2".USER_ID IS NULL THEN 1 ELSE 0 END AS C1
FROM USERS "Extent1"
LEFT OUTER JOIN USER_ACTION "Extent2" ON "Extent1".USER_ID = "Extent2".USER_ID

If I do the opposite

from user in this.Context.Users
select user.Action != null

then it gets even weirder:

SELECT
CASE WHEN "Extent3".USER_ID IS NOT NULL THEN 1 WHEN "Extent4".USER_ID IS NULL THEN 0 END AS C1
FROM USERS "Extent1"
LEFT OUTER JOIN USER_ACTION "Extent2" ON "Extent1".USER_ID = "Extent2".USER_ID
LEFT OUTER JOIN USER_ACTION "Extent3" ON "Extent2".USER_ID = "Extent3".USER_ID
LEFT OUTER JOIN USER_ACTION "Extent4" ON "Extent2".USER_ID = "Extent4".USER_ID

Now the same left outer join is generated three times!

If I do the following:

from user in this.Context.Users
let action = user.Action
select action != null

SELECT
CASE WHEN "Extent3".USER_ID IS NOT NULL THEN 1 WHEN "Extent3".USER_ID IS NULL THEN 0 END AS C1
FROM USERS "Extent1"
LEFT OUTER JOIN USER_ACTION "Extent2" ON "Extent1".USER_ID = "Extent2".USER_ID
LEFT OUTER JOIN USER_ACTION "Extent3" ON "Extent2".USER_ID = "Extent3".USER_ID

Now we're down to two left outer joins again. The sql should really have been:

SELECT
CASE WHEN "Extent2".USER_ID IS NOT NULL THEN 1 ELSE 0 END AS C1
FROM USERS "Extent1"
LEFT OUTER JOIN USER_ACTION "Extent2" ON "Extent1".USER_ID = "Extent2".USER_ID

Could Devart investigate this please?

many thanks

Remco
by Remco Blok
Tue 14 Feb 2012 11:23
Forum: Entity Framework support
Topic: Generated sql for Linq Any method
Replies: 8
Views: 2816

Generated sql for Linq Any method

Hello,

I'm curious why when you use the Linq Any method the generated sql looks something like:

CASE WHEN EXISTS (a) THEN 1 WHEN NOT EXISTS (a) THEN 0 END

where a is the same stament executed both by WHEN EXISTS and WHEN NOT EXISTS. I'm not sure how the Oracle optimiser deals with this, but I would have thought it would be better to generate the following sql instead:

CASE WHEN EXISTS (a) THEN 1 ELSE 0 END

Why is the former sql generated and not the latter?

Remco
by Remco Blok
Mon 16 Jan 2012 09:01
Forum: Entity Framework support
Topic: Auto add [Key] attribute to primary key field?
Replies: 2
Views: 1244

Hi,

This is a WCF RIA Servies question, not a Devart question. Since you're on the Devart Entity Framework forum, I assume you're using Entity Framework. Your domain service can either derive from DbDomainService when using DbContext or from LinqToEntitiesDomainSerive when using ObjectContext. In either case your Key attribute will be added automatically. This is taken care of by the DbDomainServiceDescriptionProvider or LinqToEntitiesDomainServiceDescriptionProvider attributes that these classes are decorated with. If you must derive from the base DomainService class you can always decorate your domain service with either DbDomainServiceDescriptionProvider or LinqToEntitiesDomainServiceDescriptionProvider attribute manually to have the Key attribute added automatically. See http://code.msdn.microsoft.com/Task-bas ... r-2eb86fab. Note that this Key attribute will not appear in your source code. It is added at runtime. Hope that helps

Remco
by Remco Blok
Sat 14 Jan 2012 09:12
Forum: Entity Framework support
Topic: EF Code First Migrations
Replies: 6
Views: 3082

that's great, thanks!
by Remco Blok
Thu 12 Jan 2012 15:12
Forum: Entity Framework support
Topic: EF Code First Migrations
Replies: 6
Views: 3082

I just got notified by the DevArt uservoice website that DevArt has started work on the Code First Database Evolution / Database (Schema) Migration idea. Could DevArt confirm that this is Oracle provider support for EF Code First Migrations, which Microsoft will release as Entity Framework 4.3?
by Remco Blok
Fri 09 Dec 2011 09:28
Forum: Entity Framework support
Topic: EF Code First Migrations
Replies: 6
Views: 3082

Migrations also support adding unique constraints

It looks like EF Code First Migrations also support adding unique constraints. This is the top requested feature on Devart's uservoice site: http://devart.uservoice.com/forums/1051 ... rk-support. With EF Code First Migrations scheduled for RTM in EF 4.3 in early 2012 likely coming before unique constraint support in EF, it would be good to see Devart consider EF Code First Migrations first.
by Remco Blok
Tue 06 Dec 2011 13:11
Forum: Entity Framework support
Topic: EF Code First Migrations
Replies: 6
Views: 3082

EF Code First Migrations

Hi,

I just tried out the EF Code First Migrations beta 1, specifically executing database provider specific sql. I posted about it here:
http://social.msdn.microsoft.com/Forums ... e240c293c2
and I uploaded some sample code here:
http://code.msdn.microsoft.com/Recursiv ... l-bf43a96e
It would be great if DevArt's dotConnect provider for Oracle could also support EF Code First Migrations. There is a suggestion on uservoice already here: http://devart.uservoice.com/forums/1051 ... se-schema-. What are DevArt's plans to support EF Code First Migrations?

Remco