Entity Framework 3.5: change constructor of entities class - entity-framework

The default constructor in a generated Entity Framework Entities file is like this:
public ProjectEntities() : base("name=ProjectEntities", "ProjectEntities")
{
this.OnContextCreated();
}
I want to change it to:
public ProjectEntities() : base(UtilClass.GetEnvDependantConnectionStringName(), "ProjectEntities")
{
this.OnContextCreated();
}
This is because I want to have a different connection string for all the dev environments and the production environment, and have no chance they are mixed up (which is what my custom method checks).
How do I do that? This code is thrown away every time the designer file is regenerated.

You need to create another file alongside the auto-created ProjectEntities.Designer.cs, say ProjectEntities.cs. In that you use partial to extend the functionality of your entities class like this:
public partial class ProjectEntities : ObjectContext
{
partial void OnContextCreated()
{
this.Connection.ConnectionString = UtilClass.GetEnvDependantConnectionString();
}
}
The file won't then get changed when you regenerate the .Designer.cs file. You'll have to fetch the connection string yourself...

We fixed it by calling our entities ProjectEntitiesPrivate, and what was partial class ProjectEntities before, is now a non partial class ProjectEntities : ProjectEntitiesPrivate, with the constructor I need:
public class ProjectEntities: ProjectEntitiesPrivate
{
public ProjectEntities():base(UtilClass.GetEnvDependantConnectionStringName())
{
}
....

Related

How to define a BaseConfigration for all other configuration in EF7 code first?

I want to define a base configuration (for some reason) for all model configuration(which using fluent api on them), so i create BaseConfigration class:
public class BaseConfigration<T> : EntityTypeBuilder<T> where T : class
{
public BaseConfigration(InternalEntityTypeBuilder builder) :base(builder)
{
}
}
and all of other configuration inherit from it:
public class LoyaltyActivityConfig : BaseConfigration<LoyaltyActivity>
{
public LoyaltyActivityConfig(InternalEntityTypeBuilder builder) : base(builder)
{
this.Property(x => x.Title).HasMaxLength(100);
}
}
in this point all thing goes right, but when i want to introduce this configuration in OnModelCreating method:
new LoyaltyActivityConfig(modelBuilder.Entity<NotificationPlatform>());
it gives me error:
cannot convert from 'Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder' to 'Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder'
How can i do it?
As the exception message says, you are using incorrect type. During OnModelCreating you have EntityTypeBuilder<T> object. InternalEntityTypeBuilder should not be used in user code as its internal to EF core as said in documentation.
To define a BaseConfiguration which will be applied to each entity type in the model and derived by EntityTypeConfiguration, code should be organized in following manner:
public class BaseConfiguration<T> where T : class
{
public BaseConfiguration(EntityTypeBuilder<T> entityTypeBuilder)
{
// Write fluent API code here which will be applied to all entityTypes in the model
entityTypeBuilder.HasKey("Id");
}
}
public class LoyaltyActivityConfig : BaseConfiguration<LoyaltyActivity>
{
public LoyaltyActivityConfig(EntityTypeBuilder<LoyaltyActivity> entityTypeBuilder)
: base(entityTypeBuilder)
{
// Write fluent API code here which will be applied to EntityType LoyaltyActivity only
entityTypeBuilder.Property(x => x.Title).HasMaxLength(100);
}
}
Then call above code from OnModelCreating like this
new LoyaltyActivityConfig(modelBuilder.Entity<LoyaltyActivity>());
Above method will call BaseConfiguration constructor followed by EntityTypeConfiguration constructor, applying all fluent API code.
Few things to remember here,
In BaseConfiguration even if you have generic EntityTypeBuilder you will not be able to use generic methods since T is unknown type. You can define an interface which will be implemented by every T (all entity types in the model) and use generic methods afterwards. Using non-generic methods will also get you same result though. Its just matter of readability.
You can also use method calls instead of constructor in Config classes to achieve the same.
To organize code like above, IEntityTypeConfiguration<TEntity> feature from EF6 has been implemented in EF core and will be available in 2.0 release. More info https://github.com/aspnet/EntityFramework/issues/2805

Entity Framework Object not allowing Connection String to be passed as parameter

I am trying to initialize an Entity object (ADO.NET EF Object), but it does not allow me to choose what connection string I want to use. I need to change connection string in order to give different access levels to users.
There are no overrides in the Entities Object, just a parameterless constructor.
If anyone can give me any pointers, it is appreciated.
If you have used the designer to generate an .edmx file for you, you will have something like below:
public MyEntities() : base("name=MyEntities", "MyEntities")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
This will by default, get the connection string from your configuration file.
What you could do in this case is set the connection string
public partial class MyEntities
{
partial void OnContextCreated()
{
//Dynamically Building a Connection String
this.Connection.ConnectionString = "myconnectionstring";
}
}
Bear in mind though that this will first use the base constructor to pull the connection string from config, then set it with your custom version, basically overriding the connection string. This is typically good when you always want a default connection string.
Another option if you want a bit more control, is pass the connection string in via the constructor as shown below:
public partial class MyEntities
{
public MyEntities(string connectionString) :
base(connectionString,"MyEntities")
{
this.OnContextCreated();
}
}
Now you are passing in the connection string down to the base class and this is the only one it will use. This does mean however that you will most often need to supply this each time.
Hope this helps...

Summary column on EF

Is it possible to add summary properties(no database column) according LINQ from another property(column) in EF generated class from database and this property don't update(delete or remove from class) when update model from database(because this property(cloumn) is not on database)
Yes, it is. Classed generated by Entity Framework as an Entitied are always marked partial. It lets you extend the functionality with your own properties or method.
Let say your entity class is named Post. You can extend it with code like that:
public partial class Post
{
public int Average
{
get
{
return this.Items.Average();
}
}
}
Because it's not a part of designer-generated file it won't be overwritten when it's regenerated. However, there is one requirement to make it work: your custom part of Post class has to be in exactly the same namespace as code generated by EF.
Try using the [NotMapped] attribute on a property in a partial class. This will be ignored by Entity Framework.
public partial class EntityName
{
[NotMapped]
public int CalculatedProperty
{
get
{
return Numbers.Sum();
}
}
}

Importing dependencies using a class that inherits from Lazy<>

Can you import using a class that inherits from Lazy rather than Lazy itself? I am exporting using a derivitive of ExportAttribute that contains metadata.
[FeatureExport(/* Feature Metadata Parameters */)]
public class Feature : IFeature
{
// Feature Properties
}
public class FeatureReference : Lazy<IFeature, IFeatureMetadata>
{
}
public class Consumer
{
[ImportMany]
public IEnumerable<FeatureReference> FeatureReferences { get; set; }
}
Is this possible? Would it work? I could try it myself, but I'm in development so I don't actually have any code written.
No, it won't work I'm afraid. You would need to implement your own programming model extension (either a custom part/catalog or possibly via ReflectionModelServices) to make this work.
MEF would have to create the FeatureReference object in order to set it, and considering that FeatureReference might have any constructor imaginable, you can guess why this isn't supported.

Entity Framework Code First - No Detach() method on DbContext

I'm wondering why there is no Detach method on the DbContext object like there is for ObjectContext.  I can only assume this omission was intentional, but I have a hard time figuring out why.  I need to be able to detach and re-attach entities (for putting in the cache in an ASP.NET project, for example).  However, since I can't detach an entity, when I try to attach an entity that was associated with a previous context, I get the "An entity object cannot be referenced by multiple instances of IEntityChangeTracker" exception.
What's the guidance here?  Am I missing something?
For people that might stumble upon this question, as of CTP5 you now need to write
((IObjectContextAdapter)context).ObjectContext
in order to get to ObjectContext.
DbContext uses an ObjectContext internally and EF team make this available as a protected property just in case you ever need to drop down to the lower level API and sounds like this is the case here, so you can use or expose the required functionality from a derived DbContext:
public class YourContext : DbContext
{
public void Detach(object entity)
{
ObjectContext.Detach(entity);
}
}
Then you can call this method from your controller to detach an entity.
Alternatively, you can change it to even have a richer API:
public class YourContext : DbContext
{
public void ChangeObjectState(object entity, EntityState entityState)
{
ObjectContext.ObjectStateManager.ChangeObjectState(entity, entityState);
}
}
Here is how DbContext looks like from metadata:
public class DbContext : IDisposable
{
protected System.Data.Objects.ObjectContext ObjectContext { get; }
...
}
EF:CF 4.1 RC1 and EF:CF 4.1 RTW have the same explicitly implemented IObjectContextAdapter:
public static class DbContextExtensions
{
public static void Detach(this System.Data.Entity.DbContext context, object entity)
{
((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext.Detach(entity);
}
}
Microsoft decided "Detach is too advanced technology and should be hidden". IMHO the man who invented this should be shot - because if you add brand new entity, it is otherwise difficult to just remove it without commiting changes to db (you can manipulate with DbEntityEntry but that's another story).
Edit 4 years later:
With EF6 (i somehow skipped EF5 :) ) you dont need detach() anymore, becouse removing freshly added entry does not generate delete from [table] where [Id] = 0 as in EF4 - you can just call mySet.Remove(myFreshlyCreatedAndAddedEntity) and everything will be allright.
I usually extend the base class(inherits from the DbContext) with the property:
public class MyDbContext : DbContext
{
public ObjectContext ThisObjectContext
{
get
{
return ((IObjectContextAdapter)this).ObjectContext;
}
}
}
later you can use this property for variety of useful stuff ... like Detach :)