IT:AD:EF/CodeFirst/Entities
CheckList
- http://msdn.microsoft.com/en-us/library/system.data.entity.modelconfiguration.conventions(v=vs.103).aspx
* Important: For Automapper to populate Navigation properties, etc. the properties must have a set. They can be protected, or private (Automapper can handle that, but they have to be there.- See: Mapping
* For Automapper, you'll have to state that you will be using whatever subject is there (rather than create a new one) by using the opt ⇒ opt.UseDestinationObject
Example:
.ForMember(dest => dest.WorkInstruction, opt => opt.UseDestinationValue()) //opt => opt.MapFrom(s => s)) .ForMember(dest => dest.WorkInstruction, opt => opt.MapFrom(s => s))
Requirements to enable the use of change-tracking POCO Proxies:
- Class must be public, non-abstract, non-sealed.
- Public virtual get/set for all persisted properties.
- Collection based Navigation properties must implement ICollection<T>
Ref: http://bit.ly/KgJPcU
Aggregates and Entities
Example:
Address:
public class Address
{
public virtual int Id { get; set; }
public virtual string Street { get; set; }
//...
}
User:
public class User
{
public virtual int Id { get; private set; }
//Marking *scalar* as virtual, marks it for Proxy change tracking.
public virtual string FirstName { get; set; }
//1-1 Relationship:
public virtual int BillingAddressId { get; set; }
public virtual Address BillingAddress { get; set; }
//...
//Marking a *Navigation Collection* as virtual, marks it for Lazy Loading
public virtual ICollection<Invoice> Invoices { get { return _invoices??(_invoices = new Collection<Invoice>()); } private set { _invoices = value; }}
private ICollection<Invoice> _invoices;
}
Invoice:
//See above requirements to enable the use of change-tracking POCO Proxies
public class Invoice
{
public virtual int Id { get; private set; }
//1-* Relationship:
public virtual int UserId { get; set; }
public virtual User User { get; set; }
//*-1 Relationship:
//Putting an Id above a Navigation property
// * allows setting the Item by Id
public virtual int CategoryId { get; set; }
public virtual Category Category { get; private set; }
//*-1 Relationship:
public virtual int? Category2Id { get; set; }
public virtual Category2 Category2 { get; private set; }
//1-0..1 Relationship:
public virtual int ShippingAddressId { get; set; }
public virtual Address ShippingAddress { get; set; }
//False 1-1 Relationship (ie, a Complex Type):
//Build Collections on demand:
public virtual AComplexType InvoiceDiscount { get { return _invoiceDiscount ?? (_invoiceDiscount = new AComplexType()); } }
private AComplexType _invoiceDiscount;
//1-* Relationship:
//Build Collections on demand:
public virtual ICollection<LineItem> LineItems { get { return _lineItems ?? (_lineItems = new Collection<LineItem>()); } private set { _lineItems = value; } }
private ICollection<LineItem> _lineItems;
//An unsetable, but saveable, calculated account:
public virtual decimal Total {get { return (1.00m - InvoiceDiscount.Discount) * LineItems.Sum(i => i.Amount); } private set { } }
public virtual string Summary { get; set; }
}
Category:
//See above requirements to enable the use of change-tracking POCO Proxies
public class Category
{
public virtual int Id { get; private set; }
//Note that we can remove Convention expecting ICollection<Invoice>
//and it will still create Relationship, as it is defined in FluentAPI
public virtual bool Display { get; set; }
public virtual string Text { get; set; }
}
Category2:
//See above requirements to enable the use of change-tracking POCO Proxies
public class Category2
{
public virtual int Id { get; private set; }
//Note that we can remove Convention expecting ICollection<Invoice>
//and it will still create Relationship, as it is defined in FluentAPI
public virtual bool Display { get; set; }
public virtual string Text { get; set; }
}
ComplexType:
//A complex type is one that pretends to be an separate entity, but
//is really stored in its parent table. Requirements are:
//* No Id
//* 1-1 relationship
//[ComplexType]
public class AComplexType
{
public decimal Discount { get; set; }
public string Reason { get; set; }
}
LineItem:
//See above requirements to enable the use of change-tracking POCO Proxies
public class LineItem
{
public virtual int Id { get; private set; }
public virtual int InvoiceFK { get; set; }
//Note that we can remove Nav Reference Nav back to Invoice
//and it will still create Relationship, as it is defined in FluentAPI
public virtual decimal Discount { get; set; }
public virtual int Quantity { get; set; }
public virtual int ProductFK { get; set; }
public /*virtual*/ Product Product { get; set; }
//A calculated value that is saved:
public virtual decimal Amount { get { return (1.00m - Discount) * Quantity * Product.Price; } private set { } }
}
Product:
public class Product
{
public virtual int Id { get; private set; }
public virtual string Description { get; set; }
public virtual decimal Price { get; set; }
}