Entity Framework 7 reverse engineering tool does not generate the POCOs as partials. Is there a specific reason for that?
Before EF7 we used to get partial classes so I could extend the functionality of POCOs. I was using partial classes to map the Id property to the Primary key property as shown below;
public partial class User: EntityBase
{
public override int Id
{
get { return UserId; }
set { UserId= value; }
}
}
How can I do that in EF7?
Thank you.
It was just an oversight. An Entity Framework bug was raised on this (see https://github.com/aspnet/EntityFramework/issues/3428). It was fixed today (Oct 16, 2015) - and will be in tonight's nightly build.
As a workaround the scaffold-templates approach mentioned above should work for now.
Or you are also free to just manually search and replace to add the word partial into any POCO class once it has been generated (though it would get overwritten every time you generated them again).
dnx ef dbcontext scaffold-templates EntityFramework.SqlServer
scaffold-templates command can be used to generate the EntityFramework.SqlServer.Design.DbContextTemplate.cshtml and EntityFramework.SqlServer.Design.EntityTypeTemplate.cshtml template files in the project directory to be used during scaffolding.
EntityTypeTemplate customization example to add partial class support:
....
....
#:namespace #Model.Namespace
#:{
#: public partial class #Model.EntityType.Name
#: {...
....
....
....
I am using 6.1.3 and models are generated as partials.
Related
I'm using Z.EntityFramework.Plus package to implement the audit feature in my project;
I'm following the DB first approach, I run the query that created the two audit tables as described here:
by updating the .edmx file I got those new DBsets
public virtual DbSet<AuditEntries> AuditEntries { get; set; }
public virtual DbSet<AuditEntryProperties> AuditEntryProperties { get; set; }
now I want to retrieve the audit history, I use Where extension method in Z.EntityFramework.Plus namespace:
var auditlog = AuditExtensions.Where<TbAdditions>(oContext.AuditEntries, id).ToList();
but the compiler is yelling out at me, that he can't cast the DBset<AuditEntry> to DBSet<AuditEntries> as in the Where definition it requires DbSet<AuditEntry>, not DbSet<AuditEntries>, should I change the name of the table?
Disclaimer: I'm the owner of the project Entity Framework Plus
You are currently using DB first approach with custom class AuditEntries and AuditEntryProperties. So you are not using Code First with class AuditEntry and AuditEntryProperty provided by Z.EntityFramework.Plus library.
The extension method has been made for the class provided by the library, so that's why it's incompatible with your class.
You will have to implement on your side the same extension methods found on this source: DbSet`AuditEntry.cs
Probably more extension methods will be required.
The Audit feature is supposed to be fully re-coded during the summer to allow more extensibility like this feature.
EDIT: Answer sub-question
How to implement it?
Here is an example how to implement it: https://gist.github.com/mshwf/af017b50ceb2994d953762ef2b20386d
I have an EF 5 entity called Account generated with the standard template.
It has a property AccountTypeId.
When it changes, I need a notification so another field can be updated.
How is this typically done? This is needed for only one property, so I don't want to use a modified template.
AccountTypeId is bound to a ComboBox in the UI in WinForms, so it's not really an MVVM app as I would normally do in WPF.
One way is to go to the EDMX and rename the field to AccountTypeID_Internal (for example), and in the EDMX set the property to Private. Then create a Partial Class.
Generated Account.cs should look like:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace <yournamespace>
{
using System;
using System.Collections.Generic;
public partial class Account
{
private int AccountTypeId_Internal { get; set; }
// other auto generated properties
}
}
Account.Partial.Cs
public partial class Account : INotifyPropertyChanged
{
public Int AccountTypeId
{
get
{
return this.AccountTypeId_Internal;
}
set
{
this.AccountTypeId_Internal = value;
// Do INotifyPropertyChangedLogic
}
}
// Implement INotifyPropertyChanged
}
The advantage of this is that your already written code doesn't have to change at all. The downside is that if you remove the Accout from the edmx and re-add it you will have to go through the edmx steps again.
You can do this with a few lines of code using a NuGet package called PropertyChanged.Fody. The package documentation is on GitHub. See my CodeProject tip "Adding INotifyPropertyChanged to Entity Framework Classes".
I should point out that that technique will implement INPC for every property in the class. If you only want INPC for a single property and you don't want to modify the T4 template or EDMX file then you could leverage the fact that the entity classes are generated with the "partial" keyword, allowing you to add a "wrapper" property in a separate (non-generated) file like Erik Philips described. You would have to modify your existing code to reference the wrapper property but nothing would break when you re-generate the model or entities.
I am playing around building some buildingblocks based on database tables.
So I've created an UsersManager and a ValidationManager both based on the EDMX "templates".
I'd really like to loose couple those two components with MEF. But therefore i need to create Interfaces of the entityobjects exposed in the ValidationManager.
Is there an easy way of creating those Interfaces, in that manner i can still use the EDMX generated classes?
Thanx,
Paul
Using an example of a database with a Product Table, is this what you're trying to achieve....
but still use generated entity classes (using either the standard EF generator or another POCO generator of some sort).
I'm not sure - as you mention MEF and I don't see it being directly related.
The generated entity classes are partial classes which will allow you to extend the generated class which in this case you want to extend to implement an interface.
Presuming the following interface is going to be used to introduce the layer of abstraction...
public interface IEntity {
public bool IsDeleted { get; set; }
}
Create a new class file with and extended Product class...
public partial class Product : IEntity {
public bool IsDeleted {
get {
throw new NotImplementedException();
}
set {
throw new NotImplementedException();
}
}
}
You have now extended your generated entity Product with the partial class custom code - and you can use it as normal through EF.
Now instead of your UserManager and ValidationManager classes having a hard reference to Product, instead they'll only have reference to IEntity.
If I didn't understand the question, please provide more details on exactly it is you want to do.
I am trying to use Entity Framework data migrations, as described in this post.
However, when I try to execute the Enable-Migrations step, I receive the following error in Package Manager Console:
The target context 'MyDataContext' is not constructible. Add a default constructor or provide an implementation of IDbContextFactory
So, I created a factory class that implements IDbContextFactory in the project that contains my DbContext class, but data migrations doesn't appear to recognize it.
Is there something that I should explicitly do to instruct data migrations to use this factory class?
I also hit this problem as i wrote my context to take a connection string name (and then used ninject to provide it).
The process you've gone through seems correct, here is a snippet of my class implementation if it's of any help:
public class MigrationsContextFactory : IDbContextFactory<MyContext>
{
public MyContext Create()
{
return new MyDBContext("connectionStringName");
}
}
That should be all you need.
Like #Soren pointed out, instead of using IDbContextFactory, not supported on some earlier EF Core releases (i.e. EF Core 2.1), we can implement IDesignTimeDbContextFactory<TContext>, which supports the missing ConnectionString parameter.
For a settings.json based aproach, which you can use with either of the referred interfaces, check #Arayn's sample which allows us to define "ConnectionStrings:DefaultConnection" value path
Update 1
According to #PaulWaldman's comment, on EF Core 5 support for IDbContextFactory was reintroduced. For further details, check his comment below.
I'm using entity framework designer to build entities. I found the designer really hard to use because it overwrite all your manually change after each model update using the designer. How did you round off this problem? Thanks!
What sorts of things are you manually changing? The entity still has to be mappable to the database schema.
You can extend or add functionality by declaring a partial class.
Don't make any change to the entities in the generated file -- I think it says that in the header.
All of the entities are generated as partial classes, which means you can declare "more" of the class elsewhere.
Here is an example:
public partial class Name
{
public string First { get; set; }
}
public partial class Name
{
public string Last { get; set; }
}
Although I have two different class declarations, potentially in different files and folders within the project, it gets compiled as one class.
I can now use the Name class like this:
var name = new Name();
name.First = "Jane";
name.Last = "Doe";
As you can see, the properties from both declarations are unified in an object of type Name.
To apply this to EF, leave the partial entity class alone, and declare a separate partial class with the same name to add functionality.
There is an alternative third-party tool. For more information, refer this. Currently, Devart Entity Developer doesn't include the Update From Database functionality. The Update From Database feature is on our roadmap.