Does mapping a child class in EF 4.1 require an ID property? - c#-4.0

I am starting to move some code over to EF4.1 and I am having a problem loading child classes.
I found this article and it looks like there's a way to map the child class but I was wondering if the ID columns in the parent class are required.
I thought it was "no code" to simply include a reference to the child class and the rest was taken care of.
Here's the current object model:
public class classMember
{
public int MemberID {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
}
public class classReservation
{
public int ReservationID {get; set;}
public classMember Member {get; set;}
}
But loading the classReservation just gives null Members.
Do I need to include a property for the MemberID in classReservation as well as in classMember? It seems redundant from a design point of view.

First of all, in order to have navigation properties from one entity to another, they must be declared as virtual in your POCO. So you would want this:
public class classReservation
{
public int ReservationID {get; set;}
public virtual classMember Member {get; set;}
}
This is because at runtime, EF actually subclasses your POCO using reflection. To make the navigation property work, it needs to be able to override it. This is why it has to be virtual.
To answer your second question, no, you do not need to have a "foreign key property" from the child entity to the parent entity. It helps EF, but is not necessary.
We are in the process of removing foreign key properties from our entity models. To do it, you still need to tell EF how to map the relationship in the db. This can be done in your DbContext class' OnModelCreating method:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<classReservation>
.HasRequired(r => r.classMember)
.WithMany()
.Map(x => x.MapKey("MemberId"));
}
You could also use HasOptional, WithRequiredDependent, etc, depending on the cardinality and multiplicity of the relationship.

Related

AutoMapper ProjectTo not returning navigation properties

ProjectTo works fine when entities have navigation properties and matching properties on corresponding Dtos. what am i missing ?
in my case this does not work although the query has all data :
public class Category {
....
some properties
...
public Category ParentCategory {get; set;}
}
here is the Dto
public class CategoryDto : IMapFrom<Category>
{
public void Mapping(Profile profile)
{
profile.CreateMap().ReverseMap();
}
....
some properties
...
public CategoryDto ParentCategory {get; set;}
}

ServiceStacks' Autoquery - Searching in Nested Results

I have a question relating to nested results using ServiceStack's Autoquery.
Specifically,
Firstly,
I have two classes. A Parent class with a referenced list of children, as shown below:
[Alias("view_parent")]
public class ParentView
{
public int Id { get; set; }
public string ParentName {get;set;}
[Reference]
public List<ChildView> Children {get;set;}
}
[Alias("view_children")]
public class ChildView
{
[References(typeof (ParentView))]
public int ParentId { get; set; }
public string ChildName {get;set;}
}
Secondly, I have an Autoquery class as follows:
[Route("/parents", "GET")]
public class GetParents : QueryBase<ParentView>
{
}
Given the above,
Does AutoQuery support searching within the List of children from the ParentView?
e.g. the API query
/parents?ChildName=Tom
does not seem filter the results. Does AutoQuery automatically support searching within a List?
Thanks & by the way ServiceStack is pretty awesome!
AutoQuery doesn't include any child references as part of the query. You'll need to explicitly Join tables you want included in the executed query.

Domain model - What is the proper way for a child to be added to a parent?

I have a parent and child classes. The child doesn't make sense to exist without the parent, and I want the child to have a reference to its parent.
Is this a good way to set up both the reference to the parent in the child and the child being added to the collection on the parent? Or is there a better way to do this?
public class Order
{
public Guid Id {get; private set;}
public Name Id {get; private set;}
IEnumberable<Item> Items {get; private set;}
public Order(Guid id, string name)
{
Id = id;
name = name;
Items = new List<Item>();
}
public void AddItem(Item item)
{
var items = Items.ToList();
items.Add(item);
Items = items;
}
}
public class Item
{
public Guid Id {get; private set;}
public Name Id {get; private set;}
public Order Order {get; private set;}
public Item(Guid id, string name, Order order)
{
Id = id;
name = name;
Order = order;
Order.AddItem(this);
}
}
Seems like maybe it's a bad idea to add the child to the parent's collection from within the child, but maybe it is. What's the best way to set up these relationships?
You should ask yourself "why am I trying to find the Order via the Item". Can you genuinely find a good use case?, In this case Order is the aggregate root so you should be operating via the Order. In some cases it might make sense to have a collection of Orders on the Item, if you need to find all the Orders placed on an Item for example. In that case Item will also be an aggregate root.
In your case a child should not add itself to the parent collection. A better approach, provided you need the reference to the parent, is to set the parent in the parent, in the same method where the child is added to the list. This would mean setting the item's order right after adding the item to items.

Somewhat simple automapper nested property issue

I have a many to many relationship in my application and I'm using Entity code first so it looks like this (there is obviously more to it, but this is the basic structure):
Class Ingredient{
int Id {get; set;}
string Label {get; set;}
}
Class RecipeIngredient{
Ingredient Ing {get; set;}
Recipe Rec {get; set;}
int Quantity {get; set;}
}
class Recipe{
int Id {get; set;}
List<RecipeIngredient> RecIngs {get; set;}
}
How do I handle the mapping to map this to the following DTO:
class RecipeDTO{
List<IngredientDTO> Ingredients;
}
class IngredientDTO{
int Id {get; set;}
string Label {get; set;}
int Quantity {get; set;}
}
Given that I already have the standard mappings:
Mapper.CreateMap<Recipe, RecipeDTO>();
Mapper.CreateMap<Ingredient, IngredientDTO>();
I assume I have to do some Mapper.CreateMap().ForMember() stuff, but I have no idea beyond that.
Edit: I added a couple properties to the RecipeIngredient class to make it more real world.
I figured it out.
Mapper.CreateMap<RecipeIngredient, IngredientDTO>()
.ForMember(dto => dto.Label, rc => rc.MapFrom(x => x.Ing.Label))
You have to do this for every property of Ingredient that maps to a property on IngredientDTO.

Is it ok for a DDD repository work with summary objects in addtion to "real" objects

Say I'm creating a repository to store digital E-Books as shown in the interface below. This repository will store the actual text of the book, as well as the metadata that identifies the book (title, author, publisher, ISBN etc..).
public interface IBookRepository
{
void AddBook(Book newBook);
void DeleteBook(int bookId);
void UpdateBook(Book updatedBook);
Book GetBook(int bookID)
}
public class Book
{
public int BookId {get; set;}
public string Title {get; set;}
public string Author {get; set;}
public IList<Page> Contents {get; set}
}
public class Page
{
public int PageNumber {get; set;}
public string PageContent {get; set;}
}
In most cases I would not want to retrieve the entire text for the book, as that would be rather expensive. In most cases all I care about is the metadata, for example I may simply want to create a list of books. So would it be acceptable in regards to DDD to also allow an IBookRepository to have methods that return BookSummary objects? Book summary objects would include the metadata but not the actual contents of the book.
What about having an UpdateBook(BookSummary book) method? Say I want to update the Book.Rating property, but don't need/want to read the entire contents of the book from the repository to do this.
public interface IBookRepository
{
//Full Book Methods
void AddBook(Book newBook);
void DeleteBook(int bookId);
void UpdateBook(Book updatedBook);
Book GetBook(int bookID)
//BookSummary Methods
BookSummary GetBookSummary(int bookID)
IEnumerable<BookSummary> GetBooksByAuthor(string authorName);
IEnumerable<BookSummary> GetBooksByGenre(int genreId);
void UpdateBook(BookSummary bookSummary);
}
public class BookSummary
{
public int BookId {get; set;}
public string Title {get; set;}
public string Author {get; set;}
public int PageCount {get; set;}
}
Note: I know using an ORM with Lazy Loading would also be a solution to this, but I'd like to design my repositories with out the assuming that lazy loading will be used
If there is a use case in your Domain that would support it why don't just create additional entity BookSummary with its own Repository that will do the job? It does not really matter where BookSummary is persisted - that it not relevant for the Domain.
It is important to derive Entities from the Domain using Ubiquitous language and not to look at the database structure.
public interface IBookRepository
{
//Full Book Methods
void Add(Book Book);
void Delete(Book Book);
Book findById(int bookID)
}
public interface IBookSummaryRepository
{
//Full Book Summary Methods
void Add(BookSummary BookSum);
void Delete(BookSummary BookSum);
Book findById(int bookSummaryID)
}
If you Repository has methods update() or store() it is more likely DAO than repository by DDD: http://codebetter.com/iancooper/2011/04/12/repository-saveupdate-is-a-smell/
In DDD repository should work only with aggregate root. In your case, I suppose, BookSummary is just an entity inside of Book aggregate (of course, more accurate analysis is needed here), so should get Book via BookRepository and then traverse to BookSummary from aggregate root using lazy loading. Otherwise, you are not applying Domain Driven Design here
This is an old question, however there is no accepted answer so I will answer for the benefit of people landing here from Google. I run into the issue all the time as we have many summary screens that show partial information and /or information compiled from multiple entities. What I do is use separate read models as suggested by #xelibrion in the comments of his answer. I do not employ full CQRS, just simple read models with query methods only. So your BookRepository remains like so:
public interface IBookRepository
{
void AddBook(Book newBook);
void DeleteBook(int bookId);
void UpdateBook(Book updatedBook);
Book GetBook(int bookID)
}
And your BookSummary read model and its methods look like this:
public class BookSummary
{
public int BookId {get; set;}
public string Title {get; set;}
public string Author {get; set;}
public int PageCount {get; set;}
}
public interface IBookSummaryQueries
{
BookSummary GetBookSummary(int bookID)
IEnumerable<BookSummary> GetBooksByAuthor(string authorName);
IEnumerable<BookSummary> GetBooksByGenre(int genreId);
}
Note, there are no methods to update Book here, just querying

Resources