Base class/Entity in EntityFramework 5.0
Asked Answered
R

2

8

I'm using Entity Framework 5 in Database First approach and I am using edmx file.

Most of my entities have 6 common fields. Fields like CreatedAt, CreatedBy etc. Now, I implemented some functions as extensions that can only be applied to IQueryable of those Entities that have the common fields. But when I implement the extension method, it can be accessed by any type of IQueryable as it's typed T and I can only define that the type T should always be of one type.

So, I thought I can give a base class to the entities which has common fields and define type T as that base type. But, it seems I can't do this.

Any idea on how to solve this or implement what I have explained above?

Reuven answered 16/8, 2013 at 14:23 Comment(0)
C
9

Don't create a base class. Create an Interface, like below:

public interface IMyEntity
{
    DateTime CreatedAt { get; set; }
    string CreatedBy { get; set; }
    // Other properties shared by your entities...
}

Then, your Models will be like this:

[MetadataType(typeof(MyModelMetadata))]
public partial class MyModel : IMyEntity
{
   [Bind()]  
   public class MyModelMetadata
   {
      [Required]
      public object MyProperty { get; set; }

      [Required]
      public string CreatedBy { get; set; }  
   }
}
Configurationism answered 16/8, 2013 at 14:31 Comment(8)
Thanks for your quick response. So, If I define the interface outside of edmx file. then where am I going to tell the entity to implement from that interface. It's not easy to manually edit all of the required entities as I will have to do it allover again when I update the edmx file.Reuven
You don't touch the auto-generated code. That's what partial classes are supposed to be used for. You create a partial class (under Models folder) for each of your entities in EF. That's where you can define a MetadataType for your Models (for data annotation). See the updated answer.Configurationism
Yes, I'm using MetadataType at the moment. But thought there might be an easy way of doing it i.e. like giving a base class to an entity, it would have been better if it allowed to give an interface as well within the diagram. Anyways, it loos like I will have to define the partial class for all the entities. Thanks for you quick helpReuven
What if you need to bind to the properties in IMyEntity or make them [Required]? Would you override the property in your partial class?Belligerence
Definitely the way to go. However if multiple objects are going to share the same interface, I don't recommend nesting the class in one of them.Leonardo
@TheOptimusPrimus, you don't have to do anything to bind to the properties in IMyEntity. They are just properties like the other ones. And, to use data annotation attributes like [Required] you use a MetadataType class like in the answer.Configurationism
But what if you want to make something like [CreatedAt] a [Required] attribute, but only in one instance and not the other instances? I would think you would have to override the property in your partial class?Belligerence
The MetadataType class is for a single entity not for the interface. So, you would use the attribute for the shared properties exactly the same way. However, in most cases, you don't even want to do that. You'd better share properties that are exactly the same in your entities. Fields like CreatedAt or CreatedBy are very good examples of these properties. See the updated answer.Configurationism
L
2

I'm a fan of:

public interface IShared
{
  DateTime CreatedOn { get; set; }
}

public interface ISharedValidation
{
  [Required]
  DateTime CreatedOn { get; set; }
}


public interface IMyEntity: IShared
{
  // Entity Specifics
  string Username { get; set; }
}

public interface IMyEntityValidation: ISharedValidation
{
  [Required]
  string Username { get; set; }
}

Then, your Models will be like this:

[MetadataType(typeof(IMyEntityValidation))]
public partial class MyModel : IMyEntity
{
  public object CreatedOn { get; set; }
  public string Username { get; set; }  
}

If T4 generated by Entity Framework then your non-autogenerated class would look like:

[MetadataType(typeof(IMyEntityValidation))]
public partial class MyModel : IMyEntity
{
}

Typically, it is not recommended to use Bind in Asp.Net MVC.

Leonardo answered 16/8, 2013 at 18:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.