We have a model class defined that I want to produce from our EF 4.0 edmx for persistence. The class looks roughly as follows:
[DataContract]
public class Schedule
{
[DataMember]
public string Name { get; set; }
[DataMember]
public Guid Id { get; set; }
[DataMember]
public DateTime RunDate { get; set; }
[DataMember]
public IList<Guid> Routes { get; set; }
[DataMember]
public IList<Guid> Paths { get; set; }
}
How do I represent Routes and Paths on the edmx design surface? I can't see anyway of doing this other than creating two entities with a single Guid Id field then setting a 1-* Association to Schedule. I'd rather not have to do that as we'll then have a Route and Path class that isn't what we want at the moment.
We haven't had chance to look at Code First yet and don't really have time to figure it out for this project but would it support our needs?
Thanks for any assistance.
You must either use related entities or you musn't map them directly. You can for example map another fields called RoutesSerialized and PathsSerialized which will be of type string and contains all Guids stored as strings and separated by semicolon. Your current properties will use return IEnumerable and use internally use functions like String.Join, String.Split, ToString and Guid.Parse.
Related
I'm using ASP.NET MVC5 together with EF6 and using the code first approach.
I have a property in a model that i need to to tell EF6 is NOT a foreign key:
public class LogEntry
{
public int ID { get; set; }
public int LogDayID { get; set; }
public int LogEntryTypeID { get; set; }
public int DepartmentID { get; set; }
public DateTime Clock { get; set; }
public string Text { get; set; }
public virtual LogDay LogDay { get; set; }
public virtual LogEntryType LogEntryType { get; set; }
public virtual Department Department { get; set; }
}
[NotMapped]
public class Department
{
public int ID { get; set; }
public string Title { get; set; }
}
The model Department has the [NotMapped] as this model should not be stored in the database.
I thought this was enough to make EF6 realise that DepartmentID in LogEntry shouldn't be a foreign key.. But instead it throws me an error that 'Department' is not mapped.
EDIT: Even if i remove the DepartmentID from LogEntry it still complains with the above error.
Here's the complete error message:
"The type 'SupervisorLogWeb.Models.Department' was not mapped. Check that the type has not been explicitly excluded by using the Ignore method or NotMappedAttribute data annotation. Verify that the type was defined as a class, is not primitive or generic, and does not inherit from EntityObject."
Apparently your ComplexType is discovered as a Entity - this happens, if you decided to refactor an former Entity to a ComplexType.
The ModelBuilder will decide if an type is an Entity or not (more or less) by it's presence or absence in the DbContext.
So check if your class is still defined as DbSet inside the Context and adjust accordingly.
Add the NotMapped attribute to the DeparmentID property as well. This attribute can also be applied on properties.
When all your mappings are based on conventions, EF (or any tool) can't really tell whether you broke the convention intentionally or you made a mistake. It can apply some heuristics but it's better to fail and ask the programmer than implement an unwanted mapping.
I have a model called Project
public class Project
{
[Key]
public int ID { set; get; }
public string Title { set; get; }
public string Image { set; get; }
public double? gained { set; get; }
}
I use this model with two stored procedures one returns all the properties and the other without the property gained. And I got this error
The data reader is incompatible with the specified 'Test.Models.Project'. A member of the type, 'Gained', does not have a corresponding column in the data reader with the same name.
I don't want to write separate models for each stored procedure.
How to solve that please ?
The datareader is kind of dumb in the sense that it will only match what was sent back to it. If a column is missing, it fails, as you can see.
The easiest way to solve this would be to update your second SELECT statement in your stored procedure to pass back a column named gained.
SELECT ID, Title, Image, NULL as gained FROM table
Here, we are passing back no data (NULL) as the gained column. This should make the data reader happy, keep you from needing multiple models and not send back any extra data.
The other possibility would be to use inheritance in your models. Have a base model that does not include gained, and have a second model that inherits from the base model that does include gained.
public class ProjectBase
{
[Key]
public int ID { set; get; }
public string Title { set; get; }
public string Image { set; get; }
}
public class ProjectGained : ProjectBase{
public double? gained { set; get; }
}
I've been trying to create model in EF 4.1 to represent a database schema with a single table and column holding foreign keys from two other tables, but have had little luck with both annotations and the fluent API. A sample model is shown here:
public class User
{
...
public virtual ExtendedAttribute ExtendedAttributes { get; set; }
}
public class Account
{
...
public virtual ExtendedAttribute ExtendedAttributes { get; set; }
}
public class ExtendedAttribute
{
public Guid Id {get; set;}
public Guid ItemId {get; set;} // both Account.Id and User.Id stored here
public string Value { get; set; }
}
Currently the configuration for these entities looks something like this for both User and Account modelBuilders:
this.HasOptional(u => u.ExtendedAttributes).WithRequired();
Any thoughts on how to do achieve? Many thanks.
It is even not possible with the database itself and EF will not put any abstraction for that. You must have separate column and navigation property for each entity.
My simplified domain model looks something like this:
public abstract class Entity<IdK>
{
public virtual IdK Code { get; protected set; }
}
public class Contact : Entity
{
public virtual string Name { get; set; }
public virtual Company Company { get; set; }
}
public class Company : Entity
{
public virtual string Name { get; set; }
}
and I've defined a viewmodel:
public ContactViewModel()
{
public Guid Code { get; set; }
public int Version { get; set; }
public string Name { get; set; }
public string Company { get; set; }
public List<SelectListItem> Companies { get; set; }
}
to manage my contacts in a view.
Since I want the user to be able to choose from a list of companies I've added a list of SelectedListItem which will be rendered in my view like this:
<%=Html.ListBoxFor(m => m.Company, (List<System.Web.Mvc.SelectListItem>)Model.Companies)%>
Now, when the user submits my form I remap my viewmodel with my model before I save it.
I populate my Contact and use the id of the ContactViewModel.Company to create an object of type Company to associate with the property of the Contact class.
Since I don't want to fetch the whole company from the database I just fill the id.
When I persist my contact, though, I get an exception: "not-null property references a null or transient Domain.Contact.Company".
What is the best solution to manage lookups and persistence with MVC + Nhibernate?
Do you have any suggestions from your experience?
Unfortunately with NHibernate and lookups you can't just assign the ID property to a new instance of the Company object and then assign that Company object to the Contact.
Generally what I would do is in my repository, assuming that you can't change the Company information when saving a contact is something like this:
public Contact Save(Contact contact)
{
if(contact.Company.Id > 0)
contact.Company = Session.Load<Company>(contact.Company.Id);
Session.SaveOrUpdate(contact);
}
I generally find this allows you to encapsulate the logic of loading the Company and also allows you to keep it all wrapped up nicely in a single session.
Using Session.Load in this manner avoids hitting the database as described here
If you don't do this, what you're essentially saying to NHibernate is that you have a company object which you have assigned an ID and now want to save it with all the properties set to Null or empty string values or whatever and that is not what you want.
Alternatively you could create a Save specific Domain Object that looks like this:
public abstract class Entity<IdK>
{
public virtual IdK Code { get; protected set; }
}
public class SavableContact : Entity
{
public virtual string Name { get; set; }
public virtual IdK CompanyId { get; set; }
}
Which maps directly to the Contact table in your database so that when you Save this entity you can literally just map back the CompanyId from your view model and NHibernate will only save that value back and not care at all about the company objects.
It's a case of working out what works best for you. I personally prefer the first option as the extra bit of logic helps simplify the domain model, however if you're creating and exposing a public API then the second method might make more sense.
i'd like to know, I have a application in asp.net mvc and nhibernate. I've read about that in the Views on asp.net mvc, shouldn't know about the Domain, and it need use a DTO object. So, I'm trying to do this, I found the AutoMapper component and I don't know the correct way to do my DTOS, for some domain objects. I have a domain class like this:
public class Entity
{
public virtual int Id { get; set; }
public virtual bool Active { get; set; }
}
public class Category : Entity
{
public virtual string Name { get; set; }
public virtual IList<Product> Products { get; set; }
public Category() { }
}
public class Product : Entity
{
public virtual string Name { get; set; }
public virtual string Details { get; set; }
public virtual decimal Prince { get; set; }
public virtual int Stock { get; set; }
public virtual Category Category { get; set; }
public virtual Supplier Supplier { get; set; }
public Product() { }
}
public class Supplier : Entity
{
public virtual string Name { get; set; }
public virtual IList<Product> Products { get; set; }
public Supplier() { }
}
I'd like to get some example of how can I do my DTOs to View ? Need I use only strings in DTO ? And my controllers, it should get a domain object or a DTO and transform it on a domain to save in repository ?
Thanks a lot!
Cheers
There is no guidelines on this matter and it depends on your personal chice. I have few advices that have proven useful in practice:
1. Use flat DTOs - this means that the properties of the DTO must be as primitive as possible. This saves you the need for null reference checking.
For example if you have a domain object like this:
public class Employee
{
prop string FirstName{get; set;}
prop string LastName{get; set;}
prop Employee Boss{get; set;}
...
}
And you need to output in a grid a list of employees and display information for their 1st level boss I prefer to create a DTO
public class EmployeeDTO
{
prop string FirstName{get; set;}
prop string LastName{get; set;}
prop bool HaveABoss{get;set}
prop string BossFirstName{get; set;}
prop string BossLastName{get; set;}
...
}
or something like this (-:
2. Do not convert everything to sting - this will bind the DTO to a concrete view because you'll apply special formatting. It's not a problem to apply simple formatting directly in the view.
3. Use DTOs in your post actions and than convert them to domain objects. Usually controller's actions are the first line of deffence against incorrect data and you cannot expect to be able to allways construct a valid domain object out of the user's input. In most cases you have to do some post-processing like validation, setting default values and so on. After that you can create your DTOs.