Can Fluent NHibernate's AutoMapper handle Interface types? - interface

I typed this simplified example without the benefit of an IDE so forgive any syntax errors. When I try to automap this I get a FluentConfigurationException when I attempt to compile the mappings -
"Association references unmapped class
IEmployee."
I imagine if I were to resolve this I'd get a similar error when it encounters the reference to IEmployer as well. I'm not opposed to creating a ClassMap manually but I prefer AutoMapper doing it instead.
public interface IEmployer
{
int Id{ get; set; }
IList<IEmployee> Employees { get; set; }
}
public class Employer: IEmployer
{
public int Id{ get; set; }
public IList<IEmployer> Employees { get; set; }
public Employer()
{
Employees = new List<IEmployee>();
}
}
public interface IEmployee
{
int Id { get; set; }
IEmployer Employer { get; set; }
}
public class Employee: IEmployee
{
public int Id { get; set;}
public IEmployer Employer { get; set;}
public Employee(IEmployer employer)
{
Employer = employer;
}
}
I've tried using .IncludeBase<IEmployee>() but to no avail. It acts like I never called IncludeBase at all.
Is the only solution to either not use interfaces in my domain entities or fall back on a manually defined ClassMap?
Either option creates a significant problem with the way my application is designed. I ignored persistence until I had finished implementing all the features, a mistake I won't be repeating again :-(

It's not a restriction imposed by Fluent or its AutoMapper, but by NHibernate itself.
I therefore don't think you'd get there with the manual class map. You'll have to lose the interfaces in the property and list definitions. You can keep the interfaces, but mapped properties and collections must use the concrete types of which NHibernate knows.

public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Id(x => x.Id);
Map<Address>(x => x.Address); // Person.Address is of type IAddress implemented by Address
}
}

Related

DevExpress XAF EF with TPC , abstract class is only visible in model designer at run time

I want to use Table Per Concrete Class as the inheritance strategy for my XAF Code First EF project.
I use the wizard to create the project and then paste in classes from the following
namespace Solution12.Module.BusinessObjects {
public abstract class BaseBO // abstract class helpful in getting TPC
{
[Key]
public int Id { get; set; }
public string Description { get; set; }
}
[NavigationItem("People")]
[Table("People")] // explicit table name is helpful in preventing TPH
public class Person : BaseBO
{
public string PersonName { get; set; }
}
[NavigationItem("Organisation")]
[Table("Organisations")]
public class Organisation : BaseBO
{
public string OrganisationName { get; set; }
}
public class Solution12DbContext : DbContext {
...
public DbSet<Organisation> Organisations{ get; set; }
public DbSet<Person> People { get; set; }
//public DbSet<BaseBO> baseBOs { get; set; } // having this will cause TPT instead of TPC
}
}
This all works as I want, to create the database structure.
However I cant see the abstract class in the model designer at design time.
I can see the abstract class and it's views in the model designer at run time.
How can I get the model designer to show the abstract class BaseBO at design time?
This is a significant issue for us because run-time customizations are stored in the database and hence not part of our source control.
A ticket for this problem can also be found at Dev Express Support here however this is a more concise statement of what we now understand to be the problem.
It seems that if we pop the following into each concrete class then we get the desired behavior
[NotMapped]
public BaseBO BaseBo {
get
{
return (BaseBO)this;
}
}

Value cannot be null. Parameter name: entitySet

I have a fairly standard setup with simply POCO classes
public class Project
{
public int ProjectId { get; set; }
public string Name { get; set; }
public int? ClientId { get; set; }
public virtual Client Clients { get; set; }
}
They use an interface
public interface IProjectRepository
{
IEnumerable<Project> Projects { get; }
}
and are constructed as a repository for ninject to bind to
public class EFProjectRepository : IProjectRepository
{
private EFDbContext context = new EFDbContext();
public IEnumerable<Project> Projects
{
get { return context.Projects; }
}
}
The actual context is a simply DbContext
public class EFDbContext : DbContext
{
public DbSet<Project> Projects { get; set; }
}
When I try and enable code first migrations I get the following error
I have done this exact process with other projects and there as never been an error. This is connecting to a local Sql Server Database. There does not seem to be a problem with the connection string. I have searched for this error online but the solutions seem to answer questions that do not directly relate to my setup.
I had the same issue and the cause was a POCO class that had a property of type Type.
Late to the game...but if it helps...
I had this same problem, everything was working fine, but this issue appeared, I added the following to one of my classes
public HttpPostedFileBase File { get; set; }
which seemed to break it.
I ensured I didn't map this to the database by using the following:
[NotMapped]
public HttpPostedFileBase File { get; set; }
You need to add the following using statement:
using System.ComponentModel.DataAnnotations.Schema;
Hope this helps
This problem can occur if one of the POCO classes was not declared in the DbContext.
I added them and the error went away
I had changed the name of the Task POCO class because of its association with a built in .NET name System.Threading.Tasks. However I had not changed this in the "TaskTimeLog" POCO where there was a relation. When going through the code the "Task" property in the "TaskTimeLog" POCO was not showing an error because it was now attached to that threading keyword and the reason I had changed the name in the first place.
I got this error:
Value cannot be null. Parameter name: entitySet
Turns out I was trying to join data from 2 different DbContexts.
var roles = await _identityDbContext.Roles
.AsNoTracking()
.Take(1000)
.Join(_configurationDbContext.Clients.ToList(),
a => a.ClientId,
b => b.Id,
(a,b) => new {Role = a, Client = b})
.OrderBy(x => x.Role.ClientId).ThenBy(x => x.Role.Name)
.Select(x => new RoleViewModel
{
Id = x.Role.Id,
Name = x.Role.Name,
ClientId = x.Role.ClientId,
ClientName = x.Client.ClientName
})
.ToListAsync();
The fix is to add ToList as shown. Then the join will happen in code instead of the database.
Only do this if you are OK with retrieving the whole table. (I know my "Clients" table will always be relatively small.)
For anyone not finding a resolution in the other answers, I got this error when I created a derived class from a class that had an instance in some model. The exception occurred on the first usage of my context in a request.
This is a stripped-down example that will reproduce the behaviour. Model is a DbSet in my context.
public class Model
{
public int Id { get; set; }
public Duration ExposureDuration { get; set; }
}
public class Duration
{
public int Value { get; set; }
public string Unit { get; set; }
}
//Adding this will cause the exception to occur.
public class DurationExtended : Duration
{ }
This happened during work in progress. When I changed the model property ExposureDuration to type DurationExtended, all was working again.
I had the same issue and it took quite a while to find out the solution.
In our case, we created a seperated project to handle the Entities and even if the default project in the Package Manager Console was the one handling the Entities, I need to set this project as the default project in order to make it work.
I hope this will help somebody else.
I got this error when I declared a variable of type Type - which is probably because is a complex type not supported by the DB.
When I changed it to string, the error went away
public class Sample
{
public int SampleID {get;set;}
public Type TypeInfo {get; set;} //This caused the error,
//because Type is not directly convertible
//in to a SQL datatype
}
I encountered this same issue and resolved like so:
Error in model class:
public class UserInformation
{
public string ID { get; set; }
public string AccountUserName { get; set; }
public HttpPostedFileBase ProfilePic { get; set; }
}
No error in model class
public class UserInformation
{
public string ID { get; set; }
public string AccountUserName { get; set; }
public string ProfilePicName { get; set; }
}
My issue was resolved once i updated the ProfilePic property type from HttpPostedFileBase to string. If you have a property that is not of type string, int, double or some other basic/standard type either replace such property or update to a type which SQL is more likely to accept.
Remove the line <Generator>EntityModelCodeGenerator</Generator> from your project file.
Check out this https://www.c-sharpcorner.com/UploadFile/5d065a/poco-classes-in-entity-framework/
I have some properties in "ExpenseModel", one of this was...
public virtual Type TypeId {get; set;}
which was causes the above same error because of "Type" propertyType,
so I changed "Type" => "ExpenseType" and it worked... :-)
public virtual ExpenseType TypeId {get; set;}
ExpenseModel.cs
public class ExpenseTypes
{
[Key]
public int Id { get; set; }
public string TypeName { get; set; }
public string Description { get; set; }
}
In my case I had to reference another model class called IanaTimeZone, but instead of
public virtual IanaTimeZone Timezone { get; set; }
out of rush I typed this:
public virtual TimeZone Timezone { get; set; }
and it compiled fine because VS thought it was System.TimeZone but EF6 was throwing the error. Stupid thing but took me a while to figure out, so maybe this will help someone.
To anyone else this might be helpful, I had a property TimeZone (the actual .NET TimeZone object) and this gave me the exact same error, not sure why but will dig deeper :)

EF Code First Muliple Inheritance is exclusive?

Let's say I have a model where I have the Person entity with general info (Names, Date of Birth, etc.), and two additional entities (Customer, Worker) which inherit from Person. As you see there is the option of having a Customer who CAN ALSO play the role of a Worker in the model. There is a way to design this in EF (I saw something about TPH, TPT and TPC) but I see that there is a use of discriminator which doesn't allow a Person table to include values for Worker and Customer "simultaneously".
I don't know if maybe I'm getting wrong with the general OOP concept of inheritance :S.
Thanks in advance for all your help.
You cant have multiple inheritance in .net, it is not supported (and the same applies to entity framework). You can implement multiple interfaces, but this is a slightly different notion - i.e. 'Worker' could be an interface that is implemented by some objects, such as customer
In entity framework, I believe that the discriminator is only implemented when using Table-per-hierarchy. This is where both child entities are stored in the same table, and the discriminator identifies which is which.
Table-per-type is essentially where the entities (person, customer, worker) are stored in different tables, but are accessible as single entities in your code (i.e. customer with an inheritance from person)
It may be that you need to create an interface (maybe IWorker), and create a class (maybe WorkerCustomer??) that inherits from Customer, and implements IWorker.
EDIT: 15/02/2013 19:00
Ok, so the below might be what you're looking for in terms of representing the data in a single table:
public class MyDbContext : DbContext
{
public MyDbContext() : base("TestDB")
{
}
public DbSet<Person> People { get; set; }
public DbSet<Customer> Customers { get; set; }
public DbSet<Worker> Workers { get; set; }
public DbSet<WorkerCustomer> WorkerCustomers { get; set; }
}
public class Person
{
public int ID { get; set; }
public string Name { get; set; }
}
public class Customer : Person
{
public string CustomerNumber { get; set; }
}
public interface IWorker
{
string WorkerNumber { get; set; }
}
public class Worker : Person, IWorker
{
public string WorkerNumber { get; set; }
}
public class WorkerCustomer : Customer
{
public string WorkerNumber { get; set; }
}

error when using interfaces for Entity Framework (4.2) entities

I am using the the latest version of Entity Framework (4.2) and trying to implement interfaces for my Entities and for some reason, it isn't compiling. it is throwing an error "Cannot convert expression type ICollection<IOrder> to return type ICollection<Order>". if I don't use interfaces for the entities, then I don't get this error.
I have a separate project for interfaces (for repositories and services etc) and I need to pass the EF entities in those methods as parameters and I don't want to pass the actual entities in them, because that will require the interface project to have a dependency on the EF entities.
my goal is somewhat similar to the one mentioned in this post Can I abstract Entity Framework away from my Entities?
here is the sample. I just put a sample here, my actual entities are different, but the problem is same.
public interface IOrder
{
int OrderId { get; set; }
int CustomerId { get; set; }
ICustomer Customer { get; set; }
}
public class Order : IOrder
{
public int OrderId { get; set; }
public int CustomerId { get; set; }
ICustomer Customer { get; set; }
}
public interface ICustomer
{
int CustomerId { get; set; }
ICollection<IOrder> Orders { get; set; }
}
public class Customer : ICustomer
{
public int CustomerId { get; set; }
ICollection<IOrder> Orders { get; set; }
}
public class OrderMap : EntityTypeConfiguration<Order>
{
this.HasOptional(t => t.Customer)
.WithMany(t => t.Orders) //error comes from this line
.HasForeignKey(d => d.CustomerId);
}
Entity framework is not able to work with interfaces. Your navigation properties must use the real entity types (mapped classes).
"You can add your own partial class files to specify the interfaces to be implemented - and to provide any actual implementation methods you need" - as suggested here

Creating own POCO classes wont work. ERROR Schema specified is not valid

When I try to create my own POCO classes I get this error. This is only when I got a list of some kind or acsosiation like in this case the Author got Books. But it works great when I use the T4. I kinda like to create my own classes because then I could add my AddBook() to it.. so I highly appreciate if anybody know why..
Schema specified is not valid. Errors:
The relationship 'EworkModel.AuthorBook' was not loaded because the type 'EworkModel.Book' is not available.
The following information may be useful in resolving the previous error:
The required property 'AuthorId' does not exist on the type 'EntityWork.Model.Book'.
my classes look like this
public class Author
{
public virtual int AuthorId { get; set; }
public virtual string Name { get; set; }
public List<Book> Books { get; set; }
}
public class Book
{
public virtual int BookId { get; set; }
public virtual string Title { get; set; }
public virtual Author Author { get; set; }
}
private ObjectSet<Author> _authors;
private ObjectSet<Book> _books;
public EntityWorkContext()
: base("name=EworkEntities", "EworkEntities")
{
_authors = CreateObjectSet<Author>();
_books = CreateObjectSet<Book>();
ContextOptions.LazyLoadingEnabled = true;
}
public ObjectSet<Author> Authors
{
get
{
return _authors;
}
}
public ObjectSet<Book> Books
{
get
{
return _books;
}
}
public void Save()
{
SaveChanges();
}
Seems like EF is looking for the foreign key in your Book entity. Maybe you did not exclude foreign key mapping.
Anyway, if you use the t4 generated POCOs you can still add custom methods like AddBook() by creating a partial class, because the t4 generated classes are partial.