# IT:AD:EF/CodeFirst/Entities # * [[../|(UP)]] {{indexmenu>.#2|nsort tsort}} ## CheckList ## * [MSDN:Conventions](http://bit.ly/uka0vP) * [MSDN:Code First Data Annotations](http://bit.ly/snjLx2) * 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: [[IT/AD/NET/Data/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 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 Invoices { get { return _invoices??(_invoices = new Collection()); } private set { _invoices = value; }} private ICollection _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 LineItems { get { return _lineItems ?? (_lineItems = new Collection()); } private set { _lineItems = value; } } private ICollection _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 //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 //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; } }