Skip to content

Instantly share code, notes, and snippets.

@borislitvak
Last active July 18, 2019 06:22
Show Gist options
  • Save borislitvak/cabf889345bac6d2490ddbc54e3632d0 to your computer and use it in GitHub Desktop.
Save borislitvak/cabf889345bac6d2490ddbc54e3632d0 to your computer and use it in GitHub Desktop.
What steps are needed for ObjectContext EF4 entities to coexist with DbContext EF6 ones, DbFirst? EF5 -> EF6 steps are also being mentioned.

Entity Framework: What steps are needed for EF4 entities to coexist with EF6 ones in the same dll?

In this case, EF4 entities/context are generated by Legacy ObjectContext codegen, DbFirst. The new EF6 entities/context are generated by T4 templates, DbFirst as well.

While there are some hindrances to this transformation, they can be overcome as long as any third party libraries don't use EntityFramework.dll. Let's dive into these details.

Third party libraries with EF4/ObjectContext

The libraries that I've seen are:

  • LinqKit containing AsExpandable()/.Invoke(), PredicateBuilder, etc.
  • EFExtentions containing Meterializer, .Include(), .SetMergeOption(), CreateStoreCommand(), etc - EOL
  • EntityFramework.Extended containing Batch Operations, etc - EOL

3rd party lib dependencies in legacy code

  • EntityFramework.Extended

    image

  • EFExtensions

    image

  • LinqKit

    image

Transitioning to EF6 from EF4/EF5

As EF4 DbFirst does not depend on EntityFramework.dll, it should be easier to make EF4 code coexist with EF6 code, compared to EF5. This is due to a fact that there is a single depenency on EntityFramework.dll (and, say, EntityFramework.SqlServer.dll). We are going to use this fact. Otherwise, for EF5, one has to resort to assembly aliases, specific assembly deployments, etc.

Note: EF4 code first might have depended on EntityFramework.dll, but I have no experience with this.

Model changes

There is no way around this - it you've used custom model changes in the EF4 model, namely custom types, navigation/association multiplicity, field renaming, SP mapping, enums, etc, it would not appear in your new model. You will have to do the renaming manually in the new model.

Note again that we are talking about a case whether the previous model is generated by a legacy codegen, while we want a new one to be generated by T4.

Code changes

MergeOption

Another widely used option for ObjectSet<> is to set its MergeOption to MergeOption.NoTracking. The easiest way of doing so in EF is to call this on DbQuery<> (and not DbSet<>).

Materializer/CreateStoreCommand

We can no longer use a 'Materializer', but there is a better option:

    private static readonly Materializer<DummySpReturnType> DummySpReturnTypeMaterializer = 
            new Materializer<DummySpReturnType>(r => new DummySpReturnType
            {
                P1 = r.Field<int>("p1"),
                P2 = r.Field<string>("p2"),
            });
        
        // ...

    public void f() 
    {
        using (new TransactionScope(...))
        using (var ctx = new YourObjectContextEf4()) 
        {
            DummySpReturnTypeMaterializer.Materialize(ctx.CreateStoreCommand(
                    "ef6_poc", 
                    CommandType.StoredProcedure,
                    new SqlParameter("input", 1)))
                    .ToList();
            //...
        }
    }

Becomes:

    public void f() 
    {
        using (new TransactionScope(...))
        using (var ctx = new YourDbContextEf6()) 
        {
            ctx.Database.SqlQuery<DummySpReturnType>("exec ef6_poc @input=1").ToList();
            //...
        }
    }

Other code pieces

.AsExpandable(), PredicateBuilder, .Include() remain the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment