I'm overriding OnModelCreating, and in the method there's the line base.OnModelCreating(modelBuilder);
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
Looking at code samples and manuals on how to implement this, I get confused as to wether I need it or not. Sometimes it's there, sometimes not. Sometimes at the beginning of the method, other times at the end.
What should I do with it?
According to the documentation, it doesn't matter if you inherit directly from the DbContext class:
This method is called when the model for a derived context has been initialized, but before the model has been locked down and used to initialize the context. The default implementation of this method does nothing, but it can be overridden in a derived class such that the model can be further configured before it is locked down.
In other words, since is does nothing by definition, calling base.OnModelCreating is not necessary, but at the same time will not hurt if called - that's why Sometimes it's there, sometimes not. Sometimes at the beginning of the method, other times at the end.
Here what says Pawel Kadluczka - MSFT ...
At the moment it does not really matter. Both OnModelCreating and Seed
methods don't have any implementation (i.e. the bodies of the
functions are empty) in their base classes. Therefore calling into the
base class is basically a no-op. I don't think there are any plans to
change it (especially for Seed method - how we would know what data to
put in the database?)
In general protected methods can have some implementation in base
classes. In that case this is up to the developer who derives from
such a class to decide whether s/he would like to take advantage of
the functionality provided in the method in the base class or not. If
the developer thinks that s/he only would like to add something to the
functionality provided by the method in the base class s/he would call
into this method. Otherwise s/he would not call into the method of the
base class and would provide all the required functionality in the
method on the derived class.
Reference : Link
When you override the creation you override the creation of the identity creation too. If you have not inherited any IdentityDbContext you don't need it but if you have used Identity then you have to invoke the identity's implementation too. So to invoke the identity's implementation use base.OnModelCreating(builder); So If you override the creation of Identity then Identity loses its configuration. So you run the base to preserve the creation of Identity too.
I have just begun a ASP.NET MVC5 project and based on this thread I commented "base.OnModelCreating(modelBuilder)" out.
Then I wanted to update table names etc. for the EF6 standard DbContext and when executing 'add-migration Abc' the console kept throwing this error at me:
One or more validation errors were detected during model generation:
xxx.Models.IdentityUserRole: : EntityType 'IdentityUserRole' has no key defined. Define the key for this EntityType.
xxx.Models.IdentityUserLogin: : EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType.
IdentityUserRoles: EntityType: EntitySet 'IdentityUserRoles' is based on type 'IdentityUserRole' that has no keys defined.
IdentityUserLogins: EntityType: EntitySet 'IdentityUserLogins' is based on type 'IdentityUserLogin' that has no keys defined.
After a bit of struggle, I tried un-commenting "base.OnModelCreating(modelBuilder)" and that made it all work as intended.
I have not found out exactly why, but it appears that this line of code is necessary in some cases.
Related
Do you always create these two abstract base classes as the basis of any new project in DDD?
I've read that Entity should have two things. First, an identity property, probably of a generic type. Second, an Equals() method that determines whether it's the same as another Entity. Anything else? Any other natural methods or rules of thumb?
I like to have a common abstract ancestor for all my Domain objects but that is a matter of preference and overall infrastructure requirements.
After that, yes I have abstract classes for Entity and Value objects.
Don't forget that also overriding Equals for Value objects to return equality based on equal property state can be important.
Also people frequently overlook the value of packages. Put all these core base classes in their own "kernel" library and don't be reluctant to split your domain model into multiple assemblies instead of winding up with a single large "Domain Library".
If you're using .NET/C#, I've published a set of DDD interfaces and classes for public use. Take a look to see what typically goes inside them. The embedded code comments should hint towards their usage.
You can [download it here][1]. Project is dead now.
I've never needed the Equals() method in my applications thus far. Your mileage may vary though.
However, I create empty interfaces and use them as descriptors:
public interface IAggregateRoot {}
public interface IEntity {}
public interface IValueObject {}
public class Order : IAggregateRoot
{
...
}
public class State : IValueObject
{
...
}
Is it possible to map a table column to a class field instead to a class property and how?
YOU CAN DO IT :)
Follow this link: http://weblogs.asp.net/ricardoperes/archive/2013/08/22/mapping-non-public-members-with-entity-framework-code-first.aspx
This is a common request, and really makes sense; we need to use LINQ expressions and a bit of reflection magic. First, an helper function for returning an expression that points to a member:
public static class ExpressionHelper
{
public static Expression<Func<TEntity, TResult>> GetMember<TEntity, TResult>(String memberName)
{
ParameterExpression parameter = Expression.Parameter(typeof(TEntity), "p");
MemberExpression member = Expression.MakeMemberAccess(parameter, typeof(TEntity).GetMember(memberName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Single());
Expression<Func<TEntity, TResult>> expression = Expression.Lambda<Func<TEntity, TResult>>(member, parameter);
return (expression);
}
}
Then, we call it on the DbContext.OnModelCreating method, as a parameter to StructuralTypeConfiguration.Property:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Project>().Property(ExpressionHelper.GetMember<Project, Decimal>("Budget")).IsRequired();
base.OnModelCreating(modelBuilder);
}
Entity Framework (Code First or not) does not support mapping to a field; only to properties.
UPDATE
As pointed out in the comments, these documents are a bit dated but might still help any beginner along:
Entity Framework Code first development Resources and Documentation
For the sake of completeness, heres a link to whats included in EF 4.1 RC: EF 4.1 Release Candidate Available
Changes since CTP5 (From the link above):
Rename of ‘DbDatabase’ to ‘Database’. This class has also moved
to the ‘System.Data.Entity’
namespace, along with the database
initializer classes.
Rename of ‘ModelBuilder’ to ‘DbModelBuilder’, to align with the
other core classes.
Validation in Model First and Database First. The new validation
feature was only supported in Code
First in CTP5. In RC the validation
feature will work with all three
development workflows (Model First,
Database First, and Code First).
Complete Intellisense docs. Feature CTPs were not extensively documented
because the API surface was changing
significantly between each release.
This release includes complete
documentation.
Removal of Code First Pluggable Conventions. Pluggable Conventions
were previewed in Feature CTP5 but
were not at go-live quality for this
release. This release still supports
the removal of default conventions.
Consolidation of IsIndependent in the Code First relationship API. When
configuring relationships in Feature
CTP5 the IsIndependent method was used
to identify that the relationship did
not have a foreign key property
exposed in the object model. This is
now done by calling the Map method.
HasForeignKey is still used for
relationships where the foreign key
property is exposed in the object
model.
It's one of the parameters supplied to the CreateMetadata method (which you override if extending metadata support).
ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes,
Type containerType,
Func<object> modelAccessor, <<--THIS ONE
Type modelType,
string propertyName)
I had assumed that it allowed you to access the model object itself (e.g. for setting metadata based on model values), however when I try to use it to cast to my model object I just get null.
Entity ent = (Entity)modelAccessor(); // = Null
If I've missunderstood, can anyone explain what it's purpose is? Or alternatively, how to properly use it?
Thanks
We originally had that as "object model", rather than "Func modelAccessor". We had to change it late in MVC 2's ship cycle.
The purpose is to delay retrieving the actual value of the model until such point as you know you're going to need it (that is, until you call ModelMetadata.Model).
The problem it solves is actually a rather esoteric one related to model binding against a LINQ to SQL class that has a foreign key reference in it. The problem is, if you've retrieved the child object which is represented by a foreign key relationship (which usually means a delay load of that object), then you're no longer allowed to choose a new child object by setting the foreign key ID property. It's very common to model bind the foreign key ID (and not the whole foreign key entity) when model binding, but if we'd retrieved the foreign key entity object (for the purposes of populating the ModelMetadata class) then that binding would no longer be legal, and actually throw an exception. Since ModelMetadata is used for both directions of models -- inbound, via model binding, and outbound, via HTML generation -- we needed to introduce the layer of indirection to protect your ability to use it in both scenarios without disrupting LINQ to SQL's rules.
The modelAccessor parameter does not point to an instance of the object, but rather it is a function that will access some attribute of your object. The Func "encapsulates a method that has no parameters and returns a value of the type specified by the TResult parameter." For example, if we have following class:
public class Bar(){
[DisplayName("I am Foo.")]
public string Foo{get;}
}
When the CreateMetaData is called, it will be to create meta data for the Foo property and the modelAccessor will be a function that returns the value of Foo.
I did a little digging and found a way to get to the instance of the object, but it requires using reflection. You can do the following to get the Bar class in my example:
if (modelAccessor != null)
{
//Use reflection to get the private field that holds the Bar object.
FieldInfo container = modelAccessor.Target.GetType().GetField("container");
//Invoke field on the modelAccessor target to get the instance of the Bar object.
Bar myObject = (Bar)container.GetValue(modelAccessor.Target);
}
I've only run this against a simple test case, so your mileage may vary, but hopefully this will help clarify what is going on.
I've just started using EF in VS2010. That thing is just amazin'.
I frankly can't understand something. For example I have EntityType with property, they generated from database structure.
Now, I have to simply override that property in my code. I don't need to save value of the property back into DB, but everytime when it gets read from DB it should be substituted with run-time calculated value.
Of course I can create derived class based on my EntityType but I've tried and found kinda difficulties, I'm not sure this is kinda right way to do. Anyway even when I try to change the whole EntityType to Abstract, damn Visual Studio doesn't want to validate that and says something like:
"Error 2078: The EntityType 'AssetsModel.Asset' is Abstract and can be mapped only using IsTypeOf."
"Error 2063: At least one property must be mapped in the set mapping for 'Assets'"
What the hell is this suppose to mean I dunno..
Any ideas?
The best approach would be to use Partial Classes and then create a new ReadOnly property to calculate the value in the getter.
My EF model was generated from my SQL Server database. I then generated a DomainService for RIAServices against the EF model. One of the entities is called "EntryCategories". The DomainService created this method:
public IQueryable<EntryCategories> GetEntryCategoriesSet()
{
return this.Context.EntryCategoriesSet;
}
Since my user interface display model looks quite different from the physical model, I decided to write my own DomainService for that and related entities. Yes, I know we are meant to modify the generated one but it has so much stuff in there and I wanted to focus on a small thing.
I removed the EnableClientAccess attribute from the generated DomainService and added a new class called ClientDomainService, and encapsulated in it the generated DomainService:
[EnableClientAccess()]
public class ClientDomainService : DomainService
{
// the generated domain service encapsulated in my new one.
private DataDomainService _dcds = new DataDomainService();
// reimplement one of the DataDomainService methods
public IQueryable<EntryCategories> GetEntryCategories()
{
return (from t in _dcds.GetEntryCategoriesSet() where t.EntryCategoriesVersions.EntryCategoriesVersionId == datahead.EntryCategoriesVersions.EntryCategoriesVersionId orderby t.DisplayOrder select t);
}
}
The very fist thing I tried is to reimplement the GetCateogoriesSet method but with the underlying data filtered based on another entity in my class (not shown). But when I build this, an error shows up:
Entity 'DataProject.Web.EntryCategories' has a property 'EntryCategoriesVersionsReference' with an unsupported type
If I comment out my CientDomainService, replace the EnableClientAccess attribute on the generated DomainService, and place the analagous linq filtering in the original GetEntryCategoriesSet method, the project compiles with no errors.
What is so special about the generated DomainService that my new one doesn't have? Is it that metadata.cs file?
What's special about the generated domain service is not the .metadata.cs file (you can keep it, and use it, but it doesn't solve your problem).
The problem appears somehow because RIA services (?) needs a 'domain service description provider' for the exposed Linq to EF entities. The LinqToEntitiesDomainService class has the LinqToEntitiesDomainServiceDescriptionProviderAttribute, already applied, so the generated domain services which inherit from it also inherit the provider.
When you build your own custom domain service, derived from DomainService, and expose entities through it, you need to apply this attribute yourself. Furthermore, since the provider cannot infer the object context type from the domain service base class (which it can and does if the base class is LinqToEntitiesDomainService), you need to specify the object context type in the attribute constructor, like this:
[EnableClientAccess()]
[LinqToEntitiesDomainServiceDescriptionProvider(
typeof(YourObjectContextType))]
public class ClientDomainService : DomainService
{
...
}
That should fix it.
Note that this means if you had hoped to abstract your object context away from your domain service, you'll be disappointed. I had opted for the seemingly popular repository model where all code that operates on the object context goes into a provider used by the domain service. This facilitates unit testing, but evidently doesn't remove the domain service's dependency on the object context. The context is required for RIA Services to make sense of your entites, or at least those referenced by the domain entity (such as EntryCategoriesVersions in your case).
If you want to expose a specific entity on a domain service you will have to provde at least one query method for it. This is also required when the entity is only accessed as a child of another entity.
In this case you need to add the EntryCategoriesVersions entityset to the domain service, to get the scenario working correctly.
What type is EntryCategoriesVersionsReference ? Try adding a [DataContract] annotation against the type, and appropriate [Key] and [DataMember]. It should help with marshalling.
For me, the fix for this error was to add a default constructor to the return type.
In OP's example, the property 'EntryCategories.EntryCategoriesVersionsReference' needs to be of a type with a default constructor.