EntityFramwork generating Interfaces for MEF - entity-framework

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.

Related

Is it possible to have a one-to-many relation in EF7 between two generic classes?

I have a class called GatewayClaims and a class called GatewayItems. And yes, the project I'm working on is a gateway.
I have several classes derived from GatewayItems: GatewayUser, GatewayCompany, GatewayRole and a few more. Each of these derived classes will hold claims. (Actually, just values. Simplified here.) And these claims gets passed forward to another service as a JWT token. This should work just fine.
But the problem is this:
public class GatewayClaim
{
public GatewayItem Item { get; set; } = new();
}
public abstract class GatewayItem
{
public List<GatewayClaim> Claims { get; set; } = new();
}
The "abstract" is part of the challenge here...
The problem is that I want separate tables for each item/claim pair so I have UserItems/UserClaims, CompanyItems/CompanyClaims, etc. So, preferably I would make the Claims type a generic class GatewayClaim<T> where T:GatewayItem, new() but then List<GatewayClaim> becomes invalid. And I don't weant to create a lot of derived classes just to support the various configurations that would be possible. I could use List<GatewayClaimValue<GatewayItem>> in GatewayItem which seems to work. But then I need to configure the DBSet and IEntityTypeConfiguration class for the various Claims tables and things become really messy by then.
So, I'm looking for an elegant solution to keep the amount of code to a minimum. And keep it readable!
To be clear: GatewayItem is NOT directly mapped to an entity, but a public class GatewayItemConfiguration<T> : IEntityTypeConfiguration<T> where T : GatewayItem is used to allow inheritance of basic configuration for any derived classes. This has an public virtual void Configure(EntityTypeBuilder<T> builder) method that gets overridden in the child configuration classes. Again, I'm trying to stay DRY in my code.
So the GatewayUser class uses a public class GatewayUserConfiguration : GatewayItemConfiguration<GatewayUser> {} class to configure the GatewayUser entity. I do the same way for a GatewayUserClaim which is derived from GatewayClaim at this moment. But the derived Claim types don't differ from their parent class, except the Items list is of a different type. Which is why I want to use GatewayClient<T> instead of GatewayClient.
I have several classes derived from GatewayItems: GatewayUser, GatewayCompany, GatewayRole
These are not closely-enough related to use inheritance in the database. If you want to have a common base class in code, simply don't map GatewayItem to an EF entity.
I want separate tables for each item/claim pair so I have UserItems/UserClaims
Great. Just introduce a UserClaim type, again perhaps inheriting from an unmapped Claim type, and it will map to a separate UserClaim table.

Entity Framework 5.0 inheritance with multiple assemblies

I'm using Entity Framework 5.0 with code-first approach plus inheritance for my business objects represented by Table Per Hierarchy.
I'd like to have the following structure:
//Assembly 'DataAccess'
public class MyDbContext : DbContext
{
DbSet<AbstractClass> CommonObjects.AbstractClasses { get; set; }
}
//Assembly 'CommonObjects'
public abstract class AbstractClass
{
//implementation
}
//Assembly 'DerivedObjects'
public class DerivedClass : AbstractClass
{
//implementation
}
During runtime, when trying to access the DbContext the first time, the compiler throws an InvalidOperationException saying:
The abstract type 'CommonObjects.AbstractClass' has no mapped descendents
and so cannot be mapped. Either remove 'CommonObjects.AbstractClass' from
the model or add one or more types deriving from
'CommonObjects.AbstractClass' to the model.
Is this scenario even possible? If yes, what am I doing wrong?
Thanks for your answers in advance.
Ben
Additional information:
Maybe I should be a bit more specific:
I got one assembly containing my abstract business objects (only abstractions). The concrete implementations (containing the logic) are kept in the responsible assemblies, as their logic depends upon other classes within that assembly. The issue is, I want to be able to store those conrete implementations in the persistance layer as well. But for that purpose, EF had to know those types in order to enable the mapping. But I dont want to make the persistance layer depend on my business logic layer - only the abstractions.
That's why I tried to add the derived objects to the DbContext directly from the Business Object Layer.
Example:
AbstractClass derivedClass = new DerivedClass();
MyDbContext.AbstractClasses.Add(derivedClass);
But then the exception above is being thrown. I just can't figure out a good structure to achieve this.

Binding the interface with class in mvc3 EF

Suppose I have some Interface like :
public interface IIconComponent
{
// statements ...
}
then I am implementing this interface within my class as below
public class IconComponent : IIconcomponent
{
// implementing the interface statements ..
}
and creating a Table in mvc3 like:
public class IconDBContext : DbContext
{
public DbSet<IIconComponent> Icon {get; set;} //Is this statement possible
}
That is making the set of objects of interface type for storing the class IconComponent objects in the table. How to do this in MVC3 ?
Does I have to implement some model-binder for this ? or, there exists some other method ?
Thanking you,
EF doesn't support interfaces. DbSet must be defined with the real implementation. Once you change it to use implementation your actions will most probably use it as well because there will be no reason to work with abstraction.
Why would you use entity framework is you're creating abstraction layer on top of it, it's as you're not using entity framework at all and because of that entity framework is not able to work with interfaces.
If you really need to, you can let your Entity Framework classes implement interfaces. With POCO's it's straightforward, with edmx you can make partial classes that contain the derivation from the interface. However, as said by Ladislav, something like DbSet<IIconComponent> is not possible.
I can imagine scenarios where you would want to use this, e.g. dealing with other application components that only accept specific interfaces, but that you want to populate with your EF classes. (The other day, I did exactly that with a legacy UI layer).

ASP.NET MVC | Where I should to put DataAnnotations in model

A models already exists. They are situated in another project. Where I should put DataAnotations in that project or my one? Should I use partial classes? I would like to put DataAnatation because I want javascript validation to work on client.
You can't use partial classes across assemblies, so that option is out.
You can create DTOs (data transfer objects) that are copies of the ones in the other assembly, annotate them and map.
For easy mapping you can use a tool like auto mapper. If the property names match, it will essentially do all the work for you.
Create a partial class for your Model. like this:
[MetadataType(typeof(Log_Validation))]
public partial class Log : IEntity
{
}
then create a new class Log_Validation which does all the data annotations stuff.
public class Log_Validation
{
[DisplayName("Level")]
[Required(ErrorMessage = "Please provide a level")]
public String Level { get; set; }
}

How to save manual change after a update using Entity framework designer?

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.