<|start_filename|>Source/Tests/TrackableEntities.EF.5.Tests/Mocks/MockFamily.cs<|end_filename|>
﻿using System.Collections.Generic;
using TrackableEntities.EF.Tests.FamilyModels;

namespace TrackableEntities.EF.Tests.Mocks
{
    public class MockFamily
    {
        public Parent Parent { get; private set; }

        public MockFamily()
        {
            var child1 = new Child("Child1") { Children = new List<Child>(CreateGrandChildren("Child1")) };
            var child2 = new Child("Child2") { Children = new List<Child>(CreateGrandChildren("Child2")) };
            var child3 = new Child("Child3") { Children = new List<Child>(CreateGrandChildren("Child3")) };
            Parent = new Parent("Parent")
                {
                    Children = new List<Child> { child1, child2, child3 }
                };
        }

        IEnumerable<Child> CreateGrandChildren(string childName)
        {
            var grandChild1Name = childName + "-" + "GrandChild1";
            var grandChild1 = new Child(grandChild1Name)
            {
                Children = new List<Child>
                        {
                            new Child(grandChild1Name + "-" + "GrandGrandChild1"),
                            new Child(grandChild1Name + "-" + "GrandGrandChild2"),
                            new Child(grandChild1Name + "-" + "GrandGrandChild3")
                        }
            };
            var grandChild2Name = childName + "-" + "GrandChild2";
            var grandChild2 = new Child(grandChild2Name)
            {
                Children = new List<Child>
                        {
                            new Child(grandChild2Name + "-" + "GrandGrandChild1"),
                            new Child(grandChild2Name + "-" + "GrandGrandChild2"),
                            new Child(grandChild2Name + "-" + "GrandGrandChild3")
                        }
            };
            var grandChild3Name = childName + "-" + "GrandChild3";
            var grandChild3 = new Child(grandChild3Name)
            {
                Children = new List<Child>
                        {
                            new Child(grandChild3Name + "-" + "GrandGrandChild1"),
                            new Child(grandChild3Name + "-" + "GrandGrandChild2"),
                            new Child(grandChild3Name + "-" + "GrandGrandChild3")
                        }
            };
            var result = new List<Child> {grandChild1, grandChild2, grandChild3};
            return result;
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Relations/WebApiSample.Service.Entities/Models/Product.cs<|end_filename|>
using System;
using System.Collections.Generic;
using TrackableEntities;

namespace WebApiSample.Service.Entities.Models
{
    public partial class Product : ITrackable, IMergeable
    {
        public Product()
        {
            this.OrderDetails = new List<OrderDetail>();
        }

        public int ProductId { get; set; }
        public string ProductName { get; set; }
        public Nullable<int> CategoryId { get; set; }
        public Nullable<decimal> UnitPrice { get; set; }
        public bool Discontinued { get; set; }
        public byte[] RowVersion { get; set; }
        public Category Category { get; set; }
        public List<OrderDetail> OrderDetails { get; set; }

        public TrackingState TrackingState { get; set; }
        public ICollection<string> ModifiedProperties { get; set; }
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Extensions/Common/Wizards/TrackableEntities.TemplateWizard/Constants.cs<|end_filename|>
﻿using System;

namespace TrackableEntities.TemplateWizard
{
    internal static class Constants
    {
        public static class ProjectTemplates
        {
            public const string TrackableWebApi = "TrackableWebApi";
            public const string TrackableWcfService = "TrackableWcfService";
            public const string TrackableWebApiPatterns = "TrackableWebApiPatterns";
        }

        public static class ReadMeFiles
        {
            public const string TrackableWcf = "TrackableWcf.ReadMe.txt";
            public const string TrackableWebApi = "TrackableWebApi.ReadMe.txt";
            public const string WebApiPatternsSample = "TrackableWebApi.Patterns.ReadMe.txt";
        }

        public static class ParentWizards
        {
            public const string RootWizard = "RootWizard";
            public const string EntitiesWizard = "EntitiesWizard";
        }

        public static class EntitiesTemplates
        {
            public const string ServiceNet45 = "Entities.Service.Net45";
            public const string ClientPortable = "Entities.Client.Portable";
            public const string ClientNet45 = "Entities.Client.Net45";
            public const string SharedPortable = "Entities.Shared.Portable";
            public const string SharedPortableData = "Entities.Shared.Portable.Data";
            public const string SharedNet45 = "Entities.Shared.Net45";
        }

        public static class DictionaryEntries
        {
            public const string SafeProjectName = "$safeprojectname$";
            public const string SafeRootProjectName = "$saferootprojectname$";
            public const string ParentWizardName = "$parentwizardname$";
            public const string EntitiesTemplateName = "$entitiestemplatename$";
            public const string ClientEntitiesTemplate = "$cliententitiestemplate$";
            public const string ServiceEntitiesTemplate = "$serviceentitiestemplate$";
            public const string SolutionDirectory = "$solutiondirectory$";
            public const string DestinationDirectory = "$destinationdirectory$";
            public const string OriginalDestinationDirectory = "$origdestinationdirectory$";
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Relations/WebApiSample.Service.Entities/Models/Order.cs<|end_filename|>
using System;
using System.Collections.Generic;
using TrackableEntities;

namespace WebApiSample.Service.Entities.Models
{
    public partial class Order : ITrackable, IMergeable
    {
        public Order()
        {
            this.OrderDetails = new List<OrderDetail>();
        }

        public int OrderId { get; set; }
        public string CustomerId { get; set; }
        public Nullable<System.DateTime> OrderDate { get; set; }
        public Nullable<System.DateTime> ShippedDate { get; set; }
        public Nullable<int> ShipVia { get; set; }
        public Nullable<decimal> Freight { get; set; }
        public Customer Customer { get; set; }
        public List<OrderDetail> OrderDetails { get; set; }

        public TrackingState TrackingState { get; set; }
        public ICollection<string> ModifiedProperties { get; set; }
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Source/Tests/TrackableEntities.EF.5.Tests/StateChangeInterceptorTests.cs<|end_filename|>
﻿#if EF_6
using System.Data.Entity;
#else
using System.Data;
#endif
using System.Collections.Generic;
using TrackableEntities.EF.Tests;
using TrackableEntities.EF.Tests.Mocks;
using TrackableEntities.EF.Tests.NorthwindModels;
using Xunit;

// ReSharper disable CheckNamespace
#if EF_6
namespace TrackableEntities.EF6.Tests
#else
namespace TrackableEntities.EF5.Tests
#endif
{
    public class StateChangeInterceptorTests
    {
        // ReSharper disable once InconsistentNaming
        private const CreateDbOptions CreateNorthwindDbOptions = CreateDbOptions.DropCreateDatabaseIfModelChanges;

        #region No Relationship (Product)

        [Fact]
        public void WithStateChangeInterceptor_Should_Not_Mutate_Pool()
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var product = new Product();

            bool calledX = false, calledY = false;
            var poolX = context.WithStateChangeInterceptor<Product>((e, r) => { calledX = true; return null; });
            var poolXY = poolX.WithStateChangeInterceptor<Product>((e, r) => { calledY = true; return null; });

            // Act
            poolX.ApplyChanges(product);

            // Assert
            Assert.True(calledX);
            Assert.False(calledY);
        }

        [Theory]
        [InlineData(true)]
        [InlineData(false)]
        public void State_Interceptor_Should_Change_Single_Entity_State(bool setState)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var product = new Product();
            product.TrackingState = TrackingState.Modified;

            // Act
            var state = setState ? EntityState.Unchanged : null as EntityState?;
            context
                .WithStateChangeInterceptor<Product>((e, r) => state)
                .ApplyChanges(product);

            // Assert
            var expectedState = setState ? EntityState.Unchanged : EntityState.Modified;
            Assert.Equal(expectedState, context.Entry(product).State);
        }

        [Theory]
        [InlineData(true, true)]
        [InlineData(true, false)]
        [InlineData(false, true)]
        [InlineData(false, false)]
        public void State_Interceptor_Should_Mark_Multiple_Entities_States(bool setState1, bool setState2)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var products = new List<Product>
            {
                new Product { ProductId = 1, TrackingState = TrackingState.Added },
                new Product { ProductId = 2, TrackingState = TrackingState.Deleted }
            };

            // Act
            var states = new[]
            {
                setState1 ? EntityState.Modified : null as EntityState?,
                setState2 ? EntityState.Unchanged : null as EntityState?,
            };
            context
                .WithStateChangeInterceptor<Product>((e, r) =>
                {
                    if (e.ProductId == 1)
                        return states[0];
                    if (e.ProductId == 2)
                        return states[1];
                    return null;
                })
                .ApplyChanges(products);

            // Assert
            var expectedStates = new[]
            {
                setState1 ? EntityState.Modified : EntityState.Added,
                setState2 ? EntityState.Unchanged : EntityState.Deleted,
            };
            Assert.Equal(expectedStates[0], context.Entry(products[0]).State);
            Assert.Equal(expectedStates[1], context.Entry(products[1]).State);
        }

        #endregion

        #region 1-1 Relationship (Customer - CustomerSetting)

        [Theory]
        [InlineData(true)]
        [InlineData(false)]
        public void State_Interceptor_Should_Mark_One_To_One_Entity_State(bool setState)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var nw = new MockNorthwind();
            var customer = nw.Customers[0];
            var setting = customer.CustomerSetting = new CustomerSetting { CustomerId = customer.CustomerId, Setting = "Setting1", Customer = customer };
            setting.TrackingState = TrackingState.Modified;

            // Act
            var state = setState ? EntityState.Unchanged : null as EntityState?;
            context
                .WithStateChangeInterceptor<CustomerSetting>((e, r) => state)
                .ApplyChanges(customer);

            // Assert
            var expectedState = setState ? EntityState.Unchanged : EntityState.Modified;
            Assert.Equal(expectedState, context.Entry(setting).State);
        }

        [Theory]
        [InlineData(true, true)]
        [InlineData(true, false)]
        [InlineData(false, true)]
        [InlineData(false, false)]
        public void State_Interceptor_Should_Mark_One_To_One_MultiLevel_Entities_States(bool setState1, bool setState2)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var nw = new MockNorthwind();
            var customer = nw.Customers[0];
            var setting = customer.CustomerSetting = new CustomerSetting { CustomerId = customer.CustomerId, Setting = "Setting1", Customer = customer };
            customer.TrackingState = TrackingState.Modified;
            setting.TrackingState = TrackingState.Modified;

            // Act
            var states = new[]
            {
                setState1 ? EntityState.Unchanged : null as EntityState?,
                setState2 ? EntityState.Unchanged : null as EntityState?,
            };
            context
                .WithStateChangeInterceptor<Customer>((e, r) => states[0])
                .WithStateChangeInterceptor<CustomerSetting>((e, r) => states[1])
                .ApplyChanges(customer);

            // Assert
            var expectedStates = new[]
            {
                setState1 ? EntityState.Unchanged : EntityState.Modified,
                setState2 ? EntityState.Unchanged : EntityState.Modified,
            };
            Assert.Equal(expectedStates[0], context.Entry(customer).State);
            Assert.Equal(expectedStates[1], context.Entry(setting).State);
        }

        [Theory]
        [InlineData(true)]
        [InlineData(false)]
        public void State_Interceptor_Should_Mark_One_To_One_Entity_State_With_Added_Parent(bool setState)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var nw = new MockNorthwind();
            var customer = nw.Customers[0];
            var setting = customer.CustomerSetting = new CustomerSetting { CustomerId = customer.CustomerId, Setting = "Setting1", Customer = customer };
            customer.TrackingState = TrackingState.Added;

            // Act
            var state = setState ? EntityState.Modified : null as EntityState?;
            context
                .WithStateChangeInterceptor<CustomerSetting>((e, r) => state)
                .ApplyChanges(customer);

            // Assert
            var expectedState = setState ? EntityState.Modified : EntityState.Added;
            Assert.Equal(expectedState, context.Entry(setting).State);
        }

        [Theory]
        [InlineData(true)]
        [InlineData(false)]
        public void State_Interceptor_Should_Mark_One_To_One_Entity_State_With_Deleted_Parent(bool setState)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var nw = new MockNorthwind();
            var customer = nw.Customers[0];
            var setting = customer.CustomerSetting = new CustomerSetting { CustomerId = customer.CustomerId, Setting = "Setting1", Customer = customer };
            customer.TrackingState = TrackingState.Deleted;

            // Act
            var state = setState ? EntityState.Modified : null as EntityState?;
            context
                .WithStateChangeInterceptor<CustomerSetting>((e, r) => state)
                .ApplyChanges(customer);

            // Assert
            var expectedState = setState ? EntityState.Modified : EntityState.Deleted;
            Assert.Equal(expectedState, context.Entry(setting).State);
        }

        [Theory]
        [InlineData(RelationshipType.OneToOne)]
        [InlineData(null)]
        public void State_Interceptor_Should_Mark_One_To_One_Entity_State_With_RelationType(RelationshipType? relationType)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var nw = new MockNorthwind();
            var customer = nw.Customers[0];
            var setting = customer.CustomerSetting = new CustomerSetting { CustomerId = customer.CustomerId, Setting = "Setting1", Customer = customer };
            setting.TrackingState = TrackingState.Modified;

            // Act
            var state = relationType == RelationshipType.OneToOne ? EntityState.Unchanged : null as EntityState?;
            context
                .WithStateChangeInterceptor<CustomerSetting>((e, r) => 
                    r == RelationshipType.OneToOne ? state : null)
                .ApplyChanges(customer);

            // Assert
            var expectedState = relationType == RelationshipType.OneToOne ? EntityState.Unchanged : EntityState.Modified;
            Assert.Equal(expectedState, context.Entry(setting).State);
        }

        #endregion

        #region 1-M Relationship (Order - OrderDetail)

        [Theory]
        [InlineData(true)]
        [InlineData(false)]
        public void State_Interceptor_Should_Mark_One_To_Many_Entity_State(bool setState)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var order = new MockNorthwind().Orders[0];
            var detail1 = order.OrderDetails[0];
            detail1.TrackingState = TrackingState.Modified;

            // Act
            var state = setState ? EntityState.Unchanged : null as EntityState?;
            context
                .WithStateChangeInterceptor<OrderDetail>((e, r) => state)
                .ApplyChanges(order);

            // Assert
            var expectedState = setState ? EntityState.Unchanged : EntityState.Modified;
            Assert.Equal(expectedState, context.Entry(detail1).State);
        }

        [Theory]
        [InlineData(true, true)]
        [InlineData(true, false)]
        [InlineData(false, true)]
        [InlineData(false, false)]
        public void State_Interceptor_Should_Mark_One_To_Many_Entities_States(bool setState1, bool setState2)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var order = new MockNorthwind().Orders[0];
            var detail1 = order.OrderDetails[0];
            var detail2 = order.OrderDetails[1];
            detail1.TrackingState = TrackingState.Modified;
            detail2.TrackingState = TrackingState.Modified;

            // Act
            var states = new[]
            {
                setState1 ? EntityState.Unchanged : null as EntityState?,
                setState2 ? EntityState.Unchanged : null as EntityState?,
            };
            context
                .WithStateChangeInterceptor<OrderDetail>((e, r) =>
                {
                    if (e.OrderDetailId == 1)
                        return states[0];
                    if (e.OrderDetailId == 2)
                        return states[1];
                    return null;
                })
                .ApplyChanges(order);

            // Assert
            var expectedStates = new[]
            {
                setState1 ? EntityState.Unchanged : EntityState.Modified,
                setState2 ? EntityState.Unchanged : EntityState.Modified,
            };
            Assert.Equal(expectedStates[0], context.Entry(detail1).State);
            Assert.Equal(expectedStates[1], context.Entry(detail2).State);
        }

        [Theory]
        [InlineData(true, true)]
        [InlineData(true, false)]
        [InlineData(false, true)]
        [InlineData(false, false)]
        public void State_Interceptor_Should_Mark_One_To_Many_MultiLevel_Entities_States(bool setState1, bool setState2)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var order = new MockNorthwind().Orders[0];
            var detail1 = order.OrderDetails[0];
            order.TrackingState = TrackingState.Modified;
            detail1.TrackingState = TrackingState.Modified;

            // Act
            var states = new[]
            {
                setState1 ? EntityState.Unchanged : null as EntityState?,
                setState2 ? EntityState.Unchanged : null as EntityState?,
            };
            context
                .WithStateChangeInterceptor<Order>((e, r) => states[0])
                .WithStateChangeInterceptor<OrderDetail>((e, r) => states[1])
                .ApplyChanges(order);

            // Assert
            var expectedStates = new[]
            {
                setState1 ? EntityState.Unchanged : EntityState.Modified,
                setState2 ? EntityState.Unchanged : EntityState.Modified,
            };
            Assert.Equal(expectedStates[0], context.Entry(order).State);
            Assert.Equal(expectedStates[1], context.Entry(detail1).State);
        }

        [Theory]
        [InlineData(true, false, false)]
        [InlineData(true, true, false)]
        [InlineData(true, true, true)]
        [InlineData(false, true, false)]
        [InlineData(false, true, true)]
        [InlineData(false, false, true)]
        [InlineData(false, false, false)]
        public void State_Interceptor_Should_Mark_One_To_Many_To_One_MultiLevel_Entities_States(
            bool setState1, bool setState2, bool setState3)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var order = new MockNorthwind().Orders[0];
            var detail1 = order.OrderDetails[0];
            var product = order.OrderDetails[0].Product;
            order.TrackingState = TrackingState.Modified;
            detail1.TrackingState = TrackingState.Modified;
            product.TrackingState = TrackingState.Modified;

            // Act
            var states = new[]
            {
                setState1 ? EntityState.Unchanged : null as EntityState?,
                setState2 ? EntityState.Unchanged : null as EntityState?,
                setState3 ? EntityState.Unchanged : null as EntityState?,
            };
            context
                .WithStateChangeInterceptor<Order>((e, r) => states[0])
                .WithStateChangeInterceptor<OrderDetail>((e, r) => states[1])
                .WithStateChangeInterceptor<Product>((e, r) => states[2])
                .ApplyChanges(order);

            // Assert
            var expectedStates = new[]
            {
                setState1 ? EntityState.Unchanged : EntityState.Modified,
                setState2 ? EntityState.Unchanged : EntityState.Modified,
                setState3 ? EntityState.Unchanged : EntityState.Modified,
            };
            Assert.Equal(expectedStates[0], context.Entry(order).State);
            Assert.Equal(expectedStates[1], context.Entry(detail1).State);
            Assert.Equal(expectedStates[2], context.Entry(product).State);
        }

        [Theory]
        [InlineData(true)]
        [InlineData(false)]
        public void State_Interceptor_Should_Mark_One_To_Many_Entity_State_With_Added_Parent(bool setState)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var order = new MockNorthwind().Orders[0];
            var detail1 = order.OrderDetails[0];
            order.TrackingState = TrackingState.Added;

            // Act
            var state = setState ? EntityState.Modified : null as EntityState?;
            context
                .WithStateChangeInterceptor<OrderDetail>((e, r) => state)
                .ApplyChanges(order);

            // Assert
            var expectedState = setState ? EntityState.Modified : EntityState.Added;
            Assert.Equal(expectedState, context.Entry(detail1).State);
        }

        [Theory]
        [InlineData(true)]
        [InlineData(false)]
        public void State_Interceptor_Should_Mark_One_To_Many_Entity_State_With_Deleted_Parent(bool setState)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var order = new MockNorthwind().Orders[0];
            var detail1 = order.OrderDetails[0];
            order.TrackingState = TrackingState.Deleted;

            // Act
            var state = setState ? EntityState.Modified : null as EntityState?;
            context
                .WithStateChangeInterceptor<OrderDetail>((e, r) => state)
                .ApplyChanges(order);

            // Assert
            var expectedState = setState ? EntityState.Modified : EntityState.Deleted;
            Assert.Equal(expectedState, context.Entry(detail1).State);
        }

        [Theory]
        [InlineData(RelationshipType.OneToMany)]
        [InlineData(null)]
        public void State_Interceptor_Should_Mark_One_To_Many_Entity_State_With_RelationType(RelationshipType? relationType)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var order = new MockNorthwind().Orders[0];
            var detail1 = order.OrderDetails[0];
            detail1.TrackingState = TrackingState.Modified;

            // Act
            var state = relationType == RelationshipType.OneToMany ? EntityState.Unchanged : null as EntityState?;
            context
                .WithStateChangeInterceptor<OrderDetail>((e, r) =>
                    r == RelationshipType.OneToMany ? state : null)
                .ApplyChanges(order);

            // Assert
            var expectedState = relationType == RelationshipType.OneToMany ? EntityState.Unchanged : EntityState.Modified;
            Assert.Equal(expectedState, context.Entry(detail1).State);
        }

        #endregion

        #region M-1 Relationship (Order - Customer)

        [Theory]
        [InlineData(true)]
        [InlineData(false)]
        public void State_Interceptor_Should_Mark_Many_To_One_Entity_State(bool setState)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var nw = new MockNorthwind();
            var order = nw.Orders[0];
            var customer = order.Customer;
            customer.TrackingState = TrackingState.Modified;

            // Act
            var state = setState ? EntityState.Unchanged : null as EntityState?;
            context
                .WithStateChangeInterceptor<Customer>((e, r) => state)
                .ApplyChanges(order);

            // Assert
            var expectedState = setState ? EntityState.Unchanged : EntityState.Modified;
            Assert.Equal(expectedState, context.Entry(customer).State);
        }

        [Theory]
        [InlineData(true, true)]
        [InlineData(true, false)]
        [InlineData(false, true)]
        [InlineData(false, false)]
        public void State_Interceptor_Should_Mark_Many_To_One_MultiLevel_Entities_States(bool setState1, bool setState2)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var nw = new MockNorthwind();
            var order = nw.Orders[0];
            var customer = order.Customer;
            order.TrackingState = TrackingState.Modified;
            customer.TrackingState = TrackingState.Modified;

            // Act
            var states = new[]
            {
                setState1 ? EntityState.Unchanged : null as EntityState?,
                setState2 ? EntityState.Unchanged : null as EntityState?,
            };
            context
                .WithStateChangeInterceptor<Order>((e, r) => states[0])
                .WithStateChangeInterceptor<Customer>((e, r) => states[1])
                .ApplyChanges(order);

            // Assert
            var expectedStates = new[]
            {
                setState1 ? EntityState.Unchanged : EntityState.Modified,
                setState2 ? EntityState.Unchanged : EntityState.Modified,
            };
            Assert.Equal(expectedStates[0], context.Entry(order).State);
            Assert.Equal(expectedStates[1], context.Entry(customer).State);
        }

        [Theory]
        [InlineData(true, false, false)]
        [InlineData(true, true, false)]
        [InlineData(true, true, true)]
        [InlineData(false, true, false)]
        [InlineData(false, true, true)]
        [InlineData(false, false, true)]
        [InlineData(false, false, false)]
        public void State_Interceptor_Should_Mark_Many_To_One_To_One_MultiLevel_Entities_States(
            bool setState1, bool setState2, bool setState3)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var nw = new MockNorthwind();
            var order = nw.Orders[0];
            var customer = order.Customer;
            var setting = customer.CustomerSetting = new CustomerSetting { CustomerId = customer.CustomerId, Setting = "Setting1", Customer = customer };
            order.TrackingState = TrackingState.Modified;
            customer.TrackingState = TrackingState.Modified;
            setting.TrackingState = TrackingState.Modified;

            // Act
            var states = new[]
            {
                setState1 ? EntityState.Unchanged : null as EntityState?,
                setState2 ? EntityState.Unchanged : null as EntityState?,
                setState3 ? EntityState.Unchanged : null as EntityState?,
            };
            context
                .WithStateChangeInterceptor<Order>((e, r) => states[0])
                .WithStateChangeInterceptor<Customer>((e, r) => states[1])
                .WithStateChangeInterceptor<CustomerSetting>((e, r) => states[2])
                .ApplyChanges(order);

            // Assert
            var expectedStates = new[]
            {
                setState1 ? EntityState.Unchanged : EntityState.Modified,
                setState2 ? EntityState.Unchanged : EntityState.Modified,
                setState3 ? EntityState.Unchanged : EntityState.Modified,
            };
            Assert.Equal(expectedStates[0], context.Entry(order).State);
            Assert.Equal(expectedStates[1], context.Entry(customer).State);
            Assert.Equal(expectedStates[2], context.Entry(setting).State);
        }

        [Theory]
        [InlineData(RelationshipType.ManyToOne)]
        [InlineData(null)]
        public void State_Interceptor_Should_Mark_Many_To_One_Entity_State_With_RelationType(RelationshipType? relationType)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var nw = new MockNorthwind();
            var order = nw.Orders[0];
            var customer = order.Customer;
            customer.TrackingState = TrackingState.Modified;

            // Act
            var state = relationType == RelationshipType.ManyToOne ? EntityState.Unchanged : null as EntityState?;
            context
                .WithStateChangeInterceptor<Customer>((e, r) =>
                    r == RelationshipType.ManyToOne ? state : null)
                .ApplyChanges(order);

            // Assert
            var expectedState = relationType == RelationshipType.ManyToOne ? EntityState.Unchanged : EntityState.Modified;
            Assert.Equal(expectedState, context.Entry(customer).State);
        }

        #endregion

        #region M-M Relationship (Employees - Territories)

        [Theory]
        [InlineData(true)]
        [InlineData(false)]
        public void State_Interceptor_Should_Mark_Many_To_Many_Entity_State(bool setState)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var nw = new MockNorthwind();
            var employee = nw.Employees[0];
            var territory1 = employee.Territories[0];
            employee.Territories = new List<Territory> { territory1 };
            territory1.TrackingState = TrackingState.Modified;

            // Act
            var state = setState ? EntityState.Unchanged : null as EntityState?;
            context
                .WithStateChangeInterceptor<Territory>((e, r) => state)
                .ApplyChanges(employee);

            // Assert
            var expectedState = setState ? EntityState.Unchanged : EntityState.Modified;
            Assert.Equal(expectedState, context.Entry(territory1).State);
        }

        [Theory]
        [InlineData(true, true)]
        [InlineData(true, false)]
        [InlineData(false, true)]
        [InlineData(false, false)]
        public void State_Interceptor_Should_Mark_Many_To_Many_Entities_States(bool setState1, bool setState2)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var nw = new MockNorthwind();
            var employee = nw.Employees[0];
            var territory1 = employee.Territories[0];
            var territory2 = employee.Territories[1];
            employee.Territories = new List<Territory> { territory1, territory2 };
            territory1.TrackingState = TrackingState.Modified;
            territory2.TrackingState = TrackingState.Modified;

            // Act
            var states = new[]
            {
                setState1 ? EntityState.Unchanged : null as EntityState?,
                setState2 ? EntityState.Unchanged : null as EntityState?,
            };
            context
                .WithStateChangeInterceptor<Territory>((e, r) =>
                {
                    if (e.TerritoryId == "01581")
                        return states[0];
                    if (e.TerritoryId == "01730")
                        return states[1];
                    return null;
                })
                .ApplyChanges(employee);

            // Assert
            var expectedStates = new[]
            {
                setState1 ? EntityState.Unchanged : EntityState.Modified,
                setState2 ? EntityState.Unchanged : EntityState.Modified,
            };
            Assert.Equal(expectedStates[0], context.Entry(territory1).State);
            Assert.Equal(expectedStates[1], context.Entry(territory2).State);
        }

        [Theory]
        [InlineData(true, true)]
        [InlineData(true, false)]
        [InlineData(false, true)]
        [InlineData(false, false)]
        public void State_Interceptor_Should_Mark_Many_To_Many_MultiLevel_Entities_States(bool setState1, bool setState2)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var nw = new MockNorthwind();
            var employee = nw.Employees[0];
            var territory1 = employee.Territories[0];
            employee.Territories = new List<Territory> { territory1 };
            employee.TrackingState = TrackingState.Modified;
            territory1.TrackingState = TrackingState.Modified;

            // Act
            var states = new[]
            {
                setState1 ? EntityState.Unchanged : null as EntityState?,
                setState2 ? EntityState.Unchanged : null as EntityState?,
            };
            context
                .WithStateChangeInterceptor<Employee>((e, r) => states[0])
                .WithStateChangeInterceptor<Territory>((e, r) => states[1])
                .ApplyChanges(employee);

            // Assert
            var expectedStates = new[]
            {
                setState1 ? EntityState.Unchanged : EntityState.Modified,
                setState2 ? EntityState.Unchanged : EntityState.Modified,
            };
            Assert.Equal(expectedStates[0], context.Entry(employee).State);
            Assert.Equal(expectedStates[1], context.Entry(territory1).State);
        }

        [Theory]
        [InlineData(true)]
        [InlineData(false)]
        public void State_Interceptor_Should_Mark_Many_To_Many_Entity_State_With_Added_Child(bool setState)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var nw = new MockNorthwind();
            var employee = nw.Employees[0];
            var territory1 = employee.Territories[0];
            employee.Territories = new List<Territory> { territory1 };
            employee.TrackingState = TrackingState.Unchanged;
            territory1.TrackingState = TrackingState.Added;

            // Act
            var state = setState ? EntityState.Added : null as EntityState?;
            context
                .WithStateChangeInterceptor<Territory>((e, r) => state)
                .ApplyChanges(employee);

            // Assert
            var expectedState = setState ? EntityState.Added : EntityState.Unchanged;
            Assert.Equal(expectedState, context.Entry(territory1).State);
        }

        [Theory]
        [InlineData(RelationshipType.ManyToMany)]
        [InlineData(null)]
        public void State_Interceptor_Should_Mark_Many_To_Many_Entity_State_With_RelationType(RelationshipType? relationType)
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var nw = new MockNorthwind();
            var employee = nw.Employees[0];
            var territory1 = employee.Territories[0];
            employee.Territories = new List<Territory> { territory1 };
            employee.TrackingState = TrackingState.Unchanged;
            territory1.TrackingState = TrackingState.Added;

            // Act
            var state = relationType == RelationshipType.ManyToMany ? EntityState.Added : null as EntityState?;
            context
                .WithStateChangeInterceptor<Territory>((e, r) =>
                    r == RelationshipType.ManyToMany ? state : null)
                .ApplyChanges(employee);

            // Assert
            var expectedState = relationType == RelationshipType.ManyToMany ? EntityState.Added : EntityState.Unchanged;
            Assert.Equal(expectedState, context.Entry(territory1).State);
        }

        #endregion

        #region Multiple State Interceptors

        [Fact]
        public void Last_Interceptor_Should_Win()
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var order = new MockNorthwind().Orders[0];
            var detail1 = order.OrderDetails[0];
            var detail2 = order.OrderDetails[1];
            var detail3 = order.OrderDetails[2];

            order.TrackingState = TrackingState.Unchanged;
            detail1.TrackingState = TrackingState.Unchanged;
            detail2.TrackingState = TrackingState.Unchanged;
            detail3.TrackingState = TrackingState.Unchanged;

            var orderId = order.OrderId;
            var detailId1 = detail1.OrderDetailId;
            var detailId2 = detail2.OrderDetailId;
            var detailId3 = detail3.OrderDetailId;

            // Act
            context
                // Order -> Deleted
                .WithStateChangeInterceptor<Order>((e, rs) =>
                {
                    if (e.OrderId == orderId)
                        return EntityState.Deleted;

                    return null;
                })
                // OrderDetail 1 -> Added   <====== FINAL STATE
                // OrderDetail 2 -> Modidfied
                // OrderDetail 3 -> Deleted
                .WithStateChangeInterceptor<OrderDetail>((e, rs) =>
                {
                    if (e.OrderDetailId == detailId1)
                        return EntityState.Added;

                    if (e.OrderDetailId == detailId2)
                        return EntityState.Modified;

                    if (e.OrderDetailId == detailId3)
                        return EntityState.Deleted;

                    return null;
                })
                // Order -> Modified   <====== FINAL STATE
                .WithStateChangeInterceptor<Order>((e, rs) =>
                {
                    if (e.OrderId == orderId)
                        return EntityState.Modified;

                    return null;
                })
                // OrderDetail 2 -> Added   <====== FINAL STATE
                .WithStateChangeInterceptor<OrderDetail>((e, rs) =>
                {
                    if (e.OrderDetailId == detailId2)
                        return EntityState.Added;

                    return null;
                })
                // OrderDetail 3 -> Modified   <====== FINAL STATE
                .WithStateChangeInterceptor<OrderDetail>((e, rs) =>
                {
                    if (e.OrderDetailId == detailId3)
                        return EntityState.Modified;

                    return null;
                })
                .ApplyChanges(order);

            // Assert
            Assert.Equal(EntityState.Modified, context.Entry(order).State);
            Assert.Equal(EntityState.Added, context.Entry(detail1).State);
            Assert.Equal(EntityState.Added, context.Entry(detail2).State);
            Assert.Equal(EntityState.Modified, context.Entry(detail3).State);
        }

        #endregion
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm.WpfClient/Services/ProductServiceAgent.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using WebApiSample.Mvvm.Client.Entities.Models;

namespace WebApiSample.Mvvm.WpfClient
{
    public class ProductServiceAgent : IProductServiceAgent
    {
        public async Task<IEnumerable<Product>> GetProducts()
        {
            const string request = "api/Product";
            var response = await ServiceProxy.Instance.GetAsync(request);
            response.EnsureSuccessStatusCode();
            var result = await response.Content.ReadAsAsync<IEnumerable<Product>>(new[] { ServiceProxy.Formatter });
            return result;
        }
    }
}


<|start_filename|>Source/TrackableEntities.Common.Extended/ITrackableExtended.cs<|end_filename|>
﻿using System;

namespace TrackableEntities.Extended
{
    /// <summary>
    /// Interface implemented by entities that need extended change-tracking.
    /// </summary>
    interface ITrackableExtended<TPropertyType> : ITrackable
    {
        /// <summary>
        /// Extended change-tracking state of an entity.
        /// </summary>
        TPropertyType TrackgingStateExtended { get; set; }
    }
}


<|start_filename|>Samples/VS2012/WebApiSample/WebApiSample.Client.Entities/Models/Territory.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using TrackableEntities;
using TrackableEntities.Client;

namespace WebApiSample.Client.Entities.Models
{
    [JsonObject(IsReference = true)]
    [DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
    public partial class Territory : ModelBase<Territory>, IEquatable<Territory>, ITrackable
    {
		public Territory()
		{
			this.Employees = new ChangeTrackingCollection<Employee>();
		}

		[DataMember]
		public string TerritoryId
		{ 
			get { return _TerritoryId; }
			set
			{
				if (Equals(value, _TerritoryId)) return;
				_TerritoryId = value;
				NotifyPropertyChanged(m => m.TerritoryId);
			}
		}
		private string _TerritoryId;

		[DataMember]
		public string TerritoryDescription
		{ 
			get { return _TerritoryDescription; }
			set
			{
				if (Equals(value, _TerritoryDescription)) return;
				_TerritoryDescription = value;
				NotifyPropertyChanged(m => m.TerritoryDescription);
			}
		}
		private string _TerritoryDescription;

		[DataMember]
		public ChangeTrackingCollection<Employee> Employees
		{
			get { return _Employees; }
			set
			{
				if (value != null) value.Parent = this;
				if (Equals(value, _Employees)) return;
				_Employees = value;
				NotifyPropertyChanged(m => m.Employees);
			}
		}
		private ChangeTrackingCollection<Employee> _Employees;

        #region Change Tracking

		[DataMember]
		public TrackingState TrackingState { get; set; }

		[DataMember]
		public ICollection<string> ModifiedProperties { get; set; }

		[JsonProperty, DataMember]
		private Guid EntityIdentifier { get; set; }

		#pragma warning disable 414

		[JsonProperty, DataMember]
		private Guid _entityIdentity = default(Guid);

		#pragma warning restore 414

		bool IEquatable<Territory>.Equals(Territory other)
		{
			if (EntityIdentifier != default(Guid))
				return EntityIdentifier == other.EntityIdentifier;
			return false;
		}
        #endregion
	}
}


<|start_filename|>Samples/VS2013/WebApiSample.Patterns/WebApiSample.WebApi/Controllers/OrderController.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using TrackableEntities.Common;
using WebApiSample.Service.Entities.Models;
using WebApiSample.Service.Persistence.Exceptions;
using WebApiSample.Service.Persistence.UnitsOfWork;

namespace WebApiSample.Service.WebApi.Controllers
{
	public class OrderController : ApiController
	{
		private readonly INorthwindUnitOfWork _unitOfWork;

		public OrderController(INorthwindUnitOfWork unitOfWork)
		{
			_unitOfWork = unitOfWork;
		}

		// GET api/Order
		[ResponseType(typeof(IEnumerable<Order>))]
		public async Task<IHttpActionResult> GetOrders()
		{
			IEnumerable<Order> orders = await _unitOfWork.OrderRepository.GetOrders();	
			return Ok(orders);
		}

		// GET api/Order?customerId=ABCD
		[ResponseType(typeof(IEnumerable<Order>))]
		public async Task<IHttpActionResult> GetOrders(string customerId)
		{
			IEnumerable<Order> orders = await _unitOfWork.OrderRepository.GetOrders(customerId);
			return Ok(orders);
		}

		// GET api/Order/5
		[ResponseType(typeof(Order))]
		public async Task<IHttpActionResult> GetOrder(int id)
		{
			Order order = await _unitOfWork.OrderRepository.GetOrder(id);
			if (order == null)
			{
				return NotFound();
			}
			return Ok(order);
		}


        // POST api/Order
        [ResponseType(typeof(Order))]
        public async Task<IHttpActionResult> PostOrder(Order order)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            // Insert order
            _unitOfWork.OrderRepository.Insert(order);

            try
            {
                // Save and accept changes
                await _unitOfWork.SaveChangesAsync();
            }
            catch (UpdateException)
            {
                if (_unitOfWork.OrderRepository.Find(order.OrderId) == null)
                {
                    return Conflict();
                }
                throw;
            }

            // Load related entities and accept changes
            await _unitOfWork.OrderRepository.LoadRelatedEntitiesAsync(order);
            order.AcceptChanges();

            return CreatedAtRoute("DefaultApi", new { id = order.OrderId }, order);
        }

        // PUT api/Order
		[ResponseType(typeof(Order))]
		public async Task<IHttpActionResult> PutOrder(Order order)
		{
			if (!ModelState.IsValid)
			{
				return BadRequest(ModelState);
			}

            // Update order
            _unitOfWork.OrderRepository.Update(order);
            
            try
			{
				await _unitOfWork.SaveChangesAsync();
			}
			catch (UpdateConcurrencyException)
			{
				if (_unitOfWork.OrderRepository.Find(order.OrderId) == null)
				{
					return Conflict();
				}
				throw;
			}

            // Load related entities and accept changes
            await _unitOfWork.OrderRepository.LoadRelatedEntitiesAsync(order);
            order.AcceptChanges();
            return Ok(order);
        }

		// DELETE api/Order/5
		public async Task<IHttpActionResult> DeleteOrder(int id)
		{
            // Delete order
            bool result = await _unitOfWork.OrderRepository.DeleteOrder(id);
            if (!result) return Ok();
            
            try
			{
				await _unitOfWork.SaveChangesAsync();
			}
			catch (UpdateConcurrencyException)
			{
				if (_unitOfWork.OrderRepository.Find(id) == null)
				{
					return Conflict();
				}
				throw;
			}

            return Ok();
        }

		protected override void Dispose(bool disposing)
		{
			if (disposing)
			{
				var disposable = _unitOfWork as IDisposable;
				if (disposable != null)
					disposable.Dispose();
			}
			base.Dispose(disposing);
		}
	}
}

<|start_filename|>Samples/VS2013/WebApiSample.Relations/WebApiSample.Service.Entities/Contexts/NorthwindSlimDatabaseInitializer.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using WebApiSample.Service.Entities.Models;

namespace WebApiSample.Service.Entities.Contexts
{
    public class NorthwindSlimDatabaseInitializer : DropCreateDatabaseIfModelChanges<NorthwindSlimContext>
    {
        protected override void Seed(NorthwindSlimContext context)
        {
            AddCategories(context);
            AddProducts(context);
            AddCustomers(context);
            AddCustomerSettings(context);
            AddOrders(context);
            AddEmployees(context);
        }

        private void AddOrders(NorthwindSlimContext context)
        {
            context.Orders.Add(new Order
            {
                CustomerId = "ALFKI",
                OrderId = 1,
                OrderDate = DateTime.Today,
                ShippedDate = DateTime.Today,
                Freight = 41.34M,
                OrderDetails = new List<OrderDetail>
                {
                    new OrderDetail
                    {
                        ProductId = 1,
                        Quantity = 1,
                        UnitPrice = 10M
                    },
                    new OrderDetail
                    {
                        ProductId = 2,
                        Quantity = 2,
                        UnitPrice = 20M
                    },
                }
            });
            context.Orders.Add(new Order
            {
                CustomerId = "ALFKI",
                OrderId = 2,
                OrderDate = DateTime.Today,
                ShippedDate = DateTime.Today,
                Freight = 41.34M,
                OrderDetails = new List<OrderDetail>
                {
                    new OrderDetail
                    {
                        ProductId = 3,
                        Quantity = 3,
                        UnitPrice = 30M
                    },
                }
            });
            context.Orders.Add(new Order
            {
                CustomerId = "ANATR",
                OrderId = 3,
                OrderDate = DateTime.Today,
                ShippedDate = DateTime.Today,
                Freight = 41.34M,
                OrderDetails = new List<OrderDetail>
                {
                    new OrderDetail
                    {
                        ProductId = 2,
                        Quantity = 4,
                        UnitPrice = 20M
                    },
                }
            });
            context.Orders.Add(new Order
            {
                CustomerId = "ANTON",
                OrderId = 4,
                OrderDate = DateTime.Today,
                ShippedDate = DateTime.Today,
                Freight = 41.34M,
                OrderDetails = new List<OrderDetail>
                {
                    new OrderDetail
                    {
                        ProductId = 3,
                        Quantity = 5,
                        UnitPrice = 30M
                    },
                }
            });
        }

        private void AddCustomers(NorthwindSlimContext context)
        {
            context.Customers.Add(new Customer
            {
                CustomerId = "ALFKI",
                CompanyName = "<NAME>",
                ContactName = "<NAME>",
                City = "Berlin",
                Country = "Germany"
            });
            context.Customers.Add(new Customer
            {
                CustomerId = "ANATR",
                CompanyName = "<NAME>",
                ContactName = "<NAME>",
                City = "México D.F.",
                Country = "Mexico"
            });
            context.Customers.Add(new Customer
            {
                CustomerId = "ANTON",
                CompanyName = "<NAME>",
                ContactName = "<NAME>",
                City = "México D.F.",
                Country = "Mexico"
            });
        }

        private void AddCustomerSettings(NorthwindSlimContext context)
        {
            context.CustomerSettings.Add(new CustomerSetting
            {
                CustomerId = "ALFKI",
                Setting = "Setting1"
            });
            context.CustomerSettings.Add(new CustomerSetting
            {
                CustomerId = "ANATR",
                Setting = "Setting2"
            });
            context.CustomerSettings.Add(new CustomerSetting
            {
                CustomerId = "ANTON",
                Setting = "Setting3"
            });
        }

        private void AddProducts(NorthwindSlimContext context)
        {
            context.Products.Add(new Product
            {
                ProductId = 1,
                CategoryId = 1,
                ProductName = "Chai",
                UnitPrice = 23M
            });
            context.Products.Add(new Product
            {
                ProductId = 2,
                CategoryId = 1,
                ProductName = "Chang",
                UnitPrice = 23M
            });
            context.Products.Add(new Product
            {
                ProductId = 3,
                CategoryId = 2,
                ProductName = "Aniseed Syrup",
                UnitPrice = 23M
            });
            context.Products.Add(new Product
            {
                ProductId = 4,
                CategoryId = 2,
                ProductName = "Chef Anton's Cajun Seasoning",
                UnitPrice = 23M
            });
        }

        private void AddCategories(NorthwindSlimContext context)
        {
            context.Categories.Add(new Category
            {
                CategoryId = 1,
                CategoryName = "Beverages"
            });
            context.Categories.Add(new Category
            {
                CategoryId = 2,
                CategoryName = "Condiments"
            });
            context.Categories.Add(new Category
            {
                CategoryId = 3,
                CategoryName = "Confections"
            });
            context.Categories.Add(new Category
            {
                CategoryId = 4,
                CategoryName = "Dairy Products"
            });
            context.Categories.Add(new Category
            {
                CategoryId = 5,
                CategoryName = "Grains/Cereals"
            });
            context.Categories.Add(new Category
            {
                CategoryId = 6,
                CategoryName = "Meat/Poultry"
            });
            context.Categories.Add(new Category
            {
                CategoryId = 7,
                CategoryName = "Produce"
            });
            context.Categories.Add(new Category
            {
                CategoryId = 7,
                CategoryName = "Seafood"
            });
        }

        private void AddEmployees(NorthwindSlimContext context)
        {
            var territory1 = new Territory
            {
                TerritoryId = "01581",
                TerritoryDescription = "Westboro"
            };
            var territory2 = new Territory
            {
                TerritoryId = "01730",
                TerritoryDescription = "Bedford"
            };
            var territory3 = new Territory
            {
                TerritoryId = "01833",
                TerritoryDescription = "Georgetown"
            };
            var territory4 = new Territory
            {
                TerritoryId = "02116",
                TerritoryDescription = "Boston"
            };
            context.Employees.Add(new Employee
            {
                EmployeeId = 1,
                LastName = "Davolio",
                FirstName = "Nancy",
                BirthDate = DateTime.Parse("1948-12-08"),
                HireDate = DateTime.Parse("1992-05-01"),
                City = "Seattle",
                Country = "USA",
                Territories = new List<Territory> { territory1, territory2, territory3 }
            });
            context.Employees.Add(new Employee
            {
                EmployeeId = 2,
                LastName = "Fuller",
                FirstName = "Andrew",
                BirthDate = DateTime.Parse("1952-02-19"),
                HireDate = DateTime.Parse("1992-08-14"),
                City = "Tacoma",
                Country = "USA",
                Territories = new List<Territory> { territory2, territory3 }
            });
            context.Employees.Add(new Employee
            {
                EmployeeId = 3,
                LastName = "Leverling",
                FirstName = "Janet",
                BirthDate = DateTime.Parse("1963-08-30"),
                HireDate = DateTime.Parse("1992-05-01"),
                City = "Kirkland",
                Country = "USA",
                Territories = new List<Territory> { territory3, territory4 }
            });
            context.Employees.Add(new Employee
            {
                EmployeeId = 4,
                LastName = "Peacock",
                FirstName = "Margaret",
                BirthDate = DateTime.Parse("1937-09-19"),
                HireDate = DateTime.Parse("1993-05-03"),
                City = "Redmond",
                Country = "USA",
                Territories = new List<Territory> { territory1, territory3 }
            });
        }
    }
}


<|start_filename|>Extensions/Common/Output/Extract/ItemTemplates/TrackableWcfServiceType/TrackableWcfServiceType.cs<|end_filename|>
﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.ServiceModel;
using System.Threading.Tasks;
using TrackableEntities;
using TrackableEntities.EF6;
using TrackableEntities.Common;
//using WcfSerializationHelper;
using $entitiesNamespace$;

// NOTE: Primary key name and/or type may need to be set manually.

namespace $rootnamespace$
{
    [ServiceContract(Namespace = "urn:trackable-entities:service")]
    //[DataContractSerializerPreserveReferences] // Configure serializer to handle cyclical references
    public interface I$safeitemname$
    {
        [OperationContract]
        Task<IEnumerable<$entityName$>> Get$entitySetName$();

        [OperationContract]
        Task<$entityName$> Get$entityName$(int id);
        
        [OperationContract]
        Task<$entityName$> Update$entityName$($entityName$ entity);
        
        [OperationContract]
        Task<$entityName$> Create$entityName$($entityName$ entity);
        
        [OperationContract]
        Task<bool> Delete$entityName$(int id);
    }

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class $safeitemname$ : I$safeitemname$, IDisposable
    {
        private readonly $dbContextName$ _dbContext;

        public $safeitemname$()
        {
            _dbContext = new $dbContextName$();
        }

        public async Task<IEnumerable<$entityName$>> Get$entitySetName$()
        {
            IEnumerable<$entityName$> entities = await _dbContext.$entitySetName$
    			// TODO: Add Includes for reference and/or collection properties
                .ToListAsync();
            return entities;
        }

        public async Task<$entityName$> Get$entityName$(int id)
        {
            $entityName$ entity = await _dbContext.$entitySetName$
    			// TODO: Add Includes for reference and/or collection properties
                .SingleOrDefaultAsync(e => e.$entityName$Id == id);
            return entity;
        }

        public async Task<$entityName$> Create$entityName$($entityName$ entity)
        {
            entity.TrackingState = TrackingState.Added;
            _dbContext.ApplyChanges(entity);

            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateException updateEx)
            {
                throw new FaultException(updateEx.Message);
            }

            await _dbContext.LoadRelatedEntitiesAsync(entity);
            entity.AcceptChanges();
            return entity;
        }

        public async Task<$entityName$> Update$entityName$($entityName$ entity)
        {
            _dbContext.ApplyChanges(entity);

            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException updateEx)
            {
                throw new FaultException(updateEx.Message);
            }

            await _dbContext.LoadRelatedEntitiesAsync(entity);
            entity.AcceptChanges();
            return entity;
        }

        public async Task<bool> Delete$entityName$(int id)
        {
            $entityName$ entity = await _dbContext.$entitySetName$
			    // TODO: Include child entities if any
                .SingleOrDefaultAsync(e => e.$entityName$Id == id);
            if (entity == null)
                return false;

            entity.TrackingState = TrackingState.Deleted;
            _dbContext.ApplyChanges(entity);

            try
            {
                await _dbContext.SaveChangesAsync();
                return true;
            }
            catch (DbUpdateConcurrencyException updateEx)
            {
                throw new FaultException(updateEx.Message);
            }
        }

        public void Dispose()
        {
            var dispose = _dbContext as IDisposable;
            if (dispose != null)
            {
                _dbContext.Dispose();
            }
        }
    }
} 


<|start_filename|>Samples/VS2012/WebApiSample/WebApiSample.Service.WebApi/Controllers/CustomersController.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using TrackableEntities;
using TrackableEntities.EF5;
using TrackableEntities.Common;
using WebApiSample.Service.Entities.Contexts;
using WebApiSample.Service.Entities.Models;

namespace WebApiSample.Service.WebApi.Controllers
{
    public class CustomersController : ApiController
    {
        private readonly NorthwindSlimContext _dbContext = new NorthwindSlimContext();

        // GET api/Customer
        public IEnumerable<Customer> GetCustomers()
        {
            IEnumerable<Customer> customers = _dbContext.Customers
			    .Include(c => c.CustomerSetting)
				.ToList();

            return customers;
        }

        // GET api/Customer/5
        public Customer GetCustomer(string id)
        {
            Customer customer = _dbContext.Customers
			    .Include(c => c.CustomerSetting)
                .SingleOrDefault(c => c.CustomerId == id);

            if (customer == null)
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
            }

            return customer;
        }

        // POST api/Customer
        public HttpResponseMessage PostCustomer(Customer customer)
        {
            if (!ModelState.IsValid)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }

            customer.TrackingState = TrackingState.Added;
            _dbContext.ApplyChanges(customer);

            try
            {
                _dbContext.SaveChanges();
            }
            catch (DbUpdateException ex)
            {
                if (_dbContext.Customers.Any(c => c.CustomerId == customer.CustomerId))
                {
	                return Request.CreateErrorResponse(HttpStatusCode.Conflict, ex);
                }
                throw;
            }

            _dbContext.LoadRelatedEntities(customer);
            customer.AcceptChanges();

            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, customer);
            response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = customer.CustomerId }));
            return response;
        }

        // PUT api/Customer
        public HttpResponseMessage PutCustomer(Customer customer)
        {
            if (!ModelState.IsValid)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }

            _dbContext.ApplyChanges(customer);

            try
            {
                _dbContext.SaveChanges();
            }
            catch (DbUpdateConcurrencyException ex)
            {
                if (!_dbContext.Customers.Any(c => c.CustomerId == customer.CustomerId))
                {
	                return Request.CreateErrorResponse(HttpStatusCode.Conflict, ex);
                }
                throw;
            }

			_dbContext.LoadRelatedEntities(customer);
			customer.AcceptChanges();

            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, customer);
            return response;
        }

        // DELETE api/Customer/5
        public HttpResponseMessage DeleteCustomer(string id)
        {
            Customer customer = _dbContext.Customers
                .SingleOrDefault(c => c.CustomerId == id);
            if (customer == null)
            {
                return Request.CreateResponse(HttpStatusCode.OK);
            }

			customer.TrackingState = TrackingState.Deleted;
			_dbContext.ApplyChanges(customer);

            try
            {
                _dbContext.SaveChanges();
            }
            catch (DbUpdateConcurrencyException ex)
            {
                if (!_dbContext.Customers.Any(c => c.CustomerId == customer.CustomerId))
                {
	                return Request.CreateErrorResponse(HttpStatusCode.Conflict, ex);
                }
                throw;
            }

            return Request.CreateResponse(HttpStatusCode.OK);
        }

        protected override void Dispose(bool disposing)
        {
            _dbContext.Dispose();
            base.Dispose(disposing);
        }
    }
}

<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/Contexts/NorthwindDbInitializer.cs<|end_filename|>
﻿using System;
using System.Data.Entity;
using TrackableEntities.EF.Tests.Mocks;

namespace TrackableEntities.Tests.Acceptance.Contexts
{
    public class NorthwindDbInitializer : DropCreateDatabaseAlways<NorthwindTestDbContext>
    {
        protected override void Seed(NorthwindTestDbContext context)
        {
            var model = new MockNorthwind();
            foreach (var category in model.Categories)
            {
                context.Categories.Add(category);
            }
            foreach (var product in model.Products)
            {
                context.Products.Add(product);
            }
            foreach (var customer in model.Customers)
            {
                context.Customers.Add(customer);
            }
            foreach (var order in model.Orders)
            {
                context.Orders.Add(order);
            }
            foreach (var territory in model.Territories)
            {
                context.Territories.Add(territory);
            }
            foreach (var employee in model.Employees)
            {
                context.Employees.Add(employee);
            }
            context.SaveChanges();
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm.WpfClient/ViewModels/OrderViewModelDetail.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Threading;
using System.Collections.ObjectModel;
using TrackableEntities.Client;
using WebApiSample.Mvvm.Client.Entities.Models;

// Toolkit namespace
using SimpleMvvmToolkit;

namespace WebApiSample.Mvvm.WpfClient
{
    /// <summary>
    /// This class extends ViewModelDetailBase which implements IEditableDataObject.
    /// <para>
    /// Specify type being edited <strong>DetailType</strong> as the second type argument
    /// and as a parameter to the seccond ctor.
    /// </para>
    /// <para>
    /// Use the <strong>mvvmprop</strong> snippet to add bindable properties to this ViewModel.
    /// </para>
    /// </summary>
    public class OrderViewModelDetail : ViewModelDetailBase<OrderViewModelDetail, Order>
    {
        public event EventHandler<NotificationEventArgs<Exception>> ErrorNotice;
        public event EventHandler<NotificationEventArgs<bool>> ResultNotice;

        private readonly IOrderServiceAgent _orderServiceAgent;
        private readonly IProductServiceAgent _productServiceAgent;

        public OrderViewModelDetail(IProductServiceAgent productServiceAgent,
            IOrderServiceAgent orderServiceAgent)
        {
            _productServiceAgent = productServiceAgent;
            _orderServiceAgent = orderServiceAgent;
        }

        public void Initialize(Order order)
        {
            // Set model
            Model = order;

            // Set IsNew
            IsNew = Model.OrderId == 0;

            // Set customer name
            string customerName = Model.Customer == null
                ? Model.CustomerId
                : string.Format("{0}: {1}",
            Model.CustomerId, Model.Customer.CompanyName);
            CustomerName = customerName;

            // Set window title
            WindowTitle = IsNew ? "Add Order" : "Edit Order";

            if (!IsNew)
            {
                // Begin editing
                BeginEdit();

                // Begin change tracking
                ChangeTracker = new ChangeTrackingCollection<Order>(Model);

                // Subscribe to collection changed on order details
                Model.OrderDetails.CollectionChanged += OnOrderDetailsChanged;
            }
        }

        private void OnOrderDetailsChanged(object sender, NotifyCollectionChangedEventArgs eventArgs)
        {
            if (eventArgs.Action == NotifyCollectionChangedAction.Add)
            {
                // Ensure OrderId is set on new order details
                var detail = eventArgs.NewItems.Cast<OrderDetail>().FirstOrDefault();
                if (detail != null && detail.OrderId == 0)
                    detail.OrderId = Model.OrderId;
            }
        }

        private string _windowTitle;
        public string WindowTitle
        {
            get { return _windowTitle; }
            set
            {
                _windowTitle = value;
                NotifyPropertyChanged(m => m.WindowTitle);
            }
        }

        private string _customerName;
        public string CustomerName
        {
            get { return _customerName; }
            set
            {
                _customerName = value;
                NotifyPropertyChanged(m => m.CustomerName);
            }
        }

        public bool IsNew { get; private set; }

        public ChangeTrackingCollection<Order> ChangeTracker { get; private set; }

        private List<Product> _products;
        public List<Product> Products
        {
            get { return _products; }
            set
            {
                _products = value;
                NotifyPropertyChanged(m => m.Products);
            }
        }

        public async void LoadProducts()
        {
            try
            {
                var products = await _productServiceAgent.GetProducts();
                Products = new List<Product>(products);
            }
            catch (Exception ex)
            {
                NotifyError(null, ex);
            }
        }

        public async void ConfirmSave()
        {
            if (Model == null) return;
            try
            {
                if (IsNew)
                {
                    // Save new entity
                    var createdOrder = await _orderServiceAgent.CreateOrder(Model);
                    Model = createdOrder;
                }
                else
                {
                    // Get changes, exit if none
                    var changedOrder = ChangeTracker.GetChanges().SingleOrDefault();
                    if (changedOrder == null) return;

                    // We're not changing customer
                    if (changedOrder.Customer != null)
                        changedOrder.Customer = null;

                    // Save changes
                    var updatedOrder = await _orderServiceAgent.UpdateOrder(changedOrder);
                    ChangeTracker.MergeChanges(updatedOrder);

                    // Unsubscribe to collection changed on order details
                    Model.OrderDetails.CollectionChanged -= OnOrderDetailsChanged;

                    // End editing
                    EndEdit();
                }

                // Notify view of confirmation
                Notify(ResultNotice, new NotificationEventArgs<bool>(null, true));
            }
            catch (Exception ex)
            {
                NotifyError(null, ex);
            }
        }

        public void CancelSave()
        {
            // Revert changes on modified entity
            if (!IsNew)
            {
                // Unsubscribe to collection changed on order details
                Model.OrderDetails.CollectionChanged -= OnOrderDetailsChanged;

                // Cancel editing
                CancelEdit();
            }

            // Notify view of cancellation
            Notify(ResultNotice, new NotificationEventArgs<bool>(null, false));
        }

        // Helper method to notify View of an error
        private void NotifyError(string message, Exception error)
        {
            // Notify view of an error
            Notify(ErrorNotice, new NotificationEventArgs<Exception>(message, error));
        }
    }
}

<|start_filename|>Extensions/Common/Wizards/ItemTemplateParametersWizard/ModelTypesHelper.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Windows.Forms;
using TrackableEntities;

namespace ItemTemplateParametersWizard
{
    internal static class ModelTypesHelper
    {
        public static bool SetupUserInterface(List<ModelTypeInfo> modelTypes,
            string dialogTitle, string dialogMessage, Form dialog,
            Label descLabel, ComboBox entityComboBox, ComboBox contextComboBox)
        {
            // Set dialog title and message
            dialog.Text = dialogTitle;
            descLabel.Text = dialogMessage;

            // Get trackable and context types
            List<ModelTypeInfo> entityTypes = FilterModelTypes
                (modelTypes, ModelType.Trackable);

            // Populate entity combo
            entityComboBox.DataSource = entityTypes;

            // Get dbContext types
            if (contextComboBox != null)
            {
                List<ModelTypeInfo> contextTypes = FilterModelTypes
                    (modelTypes, ModelType.DbContext);
                contextComboBox.DataSource = contextTypes;
            }
            return true;
        }

        public static ModelTypesDialogInfo GetModelTypesInfo(TextBox entitySetTextBox,
            ComboBox entityComboBox, ComboBox contextComboBox)
        {
            // Validate info
            if (!ValidateRequiredInfo(entitySetTextBox, entityComboBox,
                contextComboBox)) return null;

            // Get info
            string entitiesNamespace = ((ModelTypeInfo) entityComboBox.SelectedItem).Namespace;
            string baseNamespace = entitiesNamespace;
            int namespaceEnd = entitiesNamespace.IndexOf(".Entities.Models", StringComparison.OrdinalIgnoreCase);
            if (namespaceEnd < 0) namespaceEnd = entitiesNamespace.IndexOf(".Entities", StringComparison.OrdinalIgnoreCase);
            if (namespaceEnd >= 0) baseNamespace = entitiesNamespace.Substring(0, namespaceEnd);
            string entityName = ((ModelTypeInfo)entityComboBox.SelectedItem).Name;
            string entitySetName = entitySetTextBox.Text;
            string dbContextName = null;
            if (contextComboBox != null)
            {
                dbContextName = ((ModelTypeInfo) contextComboBox.SelectedItem).Name;
            }
            var info = new ModelTypesDialogInfo
            {
                EntityName = entityName,
                EntitySetName = entitySetName,
                DbContextName = dbContextName,
                BaseNamespace = baseNamespace,
                EntitiesNamespace = entitiesNamespace,
            };
            return info;
        }

        private static bool ValidateRequiredInfo(TextBox entitySetTextBox,
            ComboBox entityComboBox, ComboBox contextComboBox)
        {
            if (entityComboBox.SelectedIndex == -1)
            {
                MessageBox.Show("Select an Entity Name", "Entity Name");
                return false;
            }

            if (string.IsNullOrWhiteSpace(entitySetTextBox.Text))
            {
                MessageBox.Show("Enter an Entity Set Name", "Entity Set Name");
                return false;
            }

            if (contextComboBox != null && contextComboBox.SelectedIndex == -1)
            {
                MessageBox.Show("Select an DbContext Name", "DbContext Name");
                return false;
            }
            return true;
        }

        private static List<ModelTypeInfo> FilterModelTypes
            (IEnumerable<ModelTypeInfo> modelTypes, ModelType modelType)
        {
            var trackableTypes = from t in modelTypes
                where t.ModelType == modelType
                select t;
            return trackableTypes.ToList();
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm.WpfClient/Services/IOrderServiceAgent.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using WebApiSample.Mvvm.Client.Entities.Models;

namespace WebApiSample.Mvvm.WpfClient
{
    public interface IOrderServiceAgent
    {
        Task<IEnumerable<Order>> GetCustomerOrders(string customerId);

        Task<Order> GetOrder(int orderId);

        Task<Order> CreateOrder(Order order);

        Task<Order> UpdateOrder(Order order);

        Task DeleteOrder(int orderId);

        Task<bool> VerifyOrderDeleted(int orderId);
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/WebHost/WebHostServer.cs<|end_filename|>
﻿using System.Web.Http;
using System.Web.Http.SelfHost;

namespace TrackableEntities.Tests.Acceptance.WebHost
{
    public class WebHostServer
    {
        private WebHostServer() { }

        public static HttpSelfHostServer Create(int portNumber)
        {
            var config = GetHostConfig(portNumber);
            var server = new HttpSelfHostServer(config);
            return server;
        }

        private static HttpSelfHostConfiguration GetHostConfig(int portNumber)
        {
            var baseAddress = string.Format("http://{0}:{1}",
                Constants.WebHost.HostName, portNumber);
            var config = new HttpSelfHostConfiguration(baseAddress);
            config.Routes.MapHttpRoute(
                "DefaultApi",
                "api/{controller}/{id}",
                new
                {
                    id = RouteParameter.Optional
                });
            return config;
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm.WpfClient/Services/ServiceProxy.cs<|end_filename|>
﻿using System;
using System.Net.Http;
using System.Net.Http.Formatting;
using AspnetWebApi2Helpers.Serialization;

namespace WebApiSample.Mvvm.WpfClient
{
    public class ServiceProxy
    {
        private static volatile HttpClient _instance;
        private static volatile MediaTypeFormatter _formatter;
        private static readonly object SyncRoot = new object();

        private ServiceProxy() { }

        public static HttpClient Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (SyncRoot)
                    {
                        if (_instance == null)
                        {
                            var formatter = new JsonMediaTypeFormatter();
                            formatter.JsonPreserveReferences();

                            string baseAddress = string.Format("http://{0}:{1}/",
                                Constants.WebClient.ServiceHost, Constants.WebClient.PortNumber);

                            _instance = new HttpClient {BaseAddress = new Uri(baseAddress)};
                        }
                    }
                }
                return _instance;
            }
        }

        public static MediaTypeFormatter Formatter
        {
            get
            {
                if (_formatter == null)
                {
                    lock (SyncRoot)
                    {
                        if (_formatter == null)
                        {
                            var jsonFormatter = new JsonMediaTypeFormatter();
                            jsonFormatter.JsonPreserveReferences();
                            _formatter = jsonFormatter;
                        }
                    }
                }
                return _formatter;
            }
        }
    }
}


<|start_filename|>Extensions/Common/Wizards/ItemTemplateParametersWizard/ModelTypesDialogInfo.cs<|end_filename|>
﻿using System;

namespace ItemTemplateParametersWizard
{
    public class ModelTypesDialogInfo
    {
        public string EntityName { get; set; }
        public string EntitySetName { get; set; }
        public string DbContextName { get; set; }
        public string BaseNamespace { get; set; }
        public string EntitiesNamespace { get; set; }
    }
}


<|start_filename|>Extensions/Common/Wizards/TrackableEntities.TemplateWizard/EntitiesWizard.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using EntitiesSelectionWizard;
using EnvDTE;
using Microsoft.VisualStudio.TemplateWizard;

namespace TrackableEntities.TemplateWizard
{
    // Entities wizard is used by entities project vstemplate
    public class EntitiesWizard : IWizard
    {
        // Use to communicate $entitiestempaltename$ to ChildWizard
        public static Dictionary<string, string> RootDictionary =
            new Dictionary<string, string>();

        // Select entities template
        public static void SelectEntitiesTemplate(bool multiproject, string templateName)
        {
            // Disallow shared portable entities for WebApi due to Json.net compat issues:
            // Error: Method not found (Newtonsoft.Json.Serialization.DefaultContractResolver SET_IgnoreSerializableAttribute)
            bool webApiSharedPortable = templateName.Equals(Constants.ProjectTemplates.TrackableWebApi, StringComparison.InvariantCultureIgnoreCase)
                || templateName.Equals(Constants.ProjectTemplates.TrackableWebApiPatterns, StringComparison.InvariantCultureIgnoreCase);

            // Prompt user for entities template
            var dialog = new EntitiesSelectionDialog(multiproject, webApiSharedPortable);
            if (dialog.ShowDialog() == DialogResult.Cancel)
                throw new WizardBackoutException();

            // Place "$entitiestempaltename$ in entities root dictionary
            string entitiesTemplateName = GetEntitiesTemplateName(dialog.EntitiesSelection);
            RootDictionary[Constants.DictionaryEntries.EntitiesTemplateName] = entitiesTemplateName;

            // Place $cliententitiestemplate$ and $serviceentitiestemplate$ in root dictionary
            string[] entitiesTemplateNames = entitiesTemplateName.Split('|');
            RootWizard.RootDictionary[Constants.DictionaryEntries.ClientEntitiesTemplate] = entitiesTemplateNames[0];
            if (entitiesTemplateNames.Length == 2)
                RootWizard.RootDictionary[Constants.DictionaryEntries.ServiceEntitiesTemplate] = entitiesTemplateNames[1];
            else
                RootWizard.RootDictionary[Constants.DictionaryEntries.ServiceEntitiesTemplate] = entitiesTemplateNames[0];
        }

        // Add global replacement parameters
        public void RunStarted(object automationObject, 
            Dictionary<string, string> replacementsDictionary, 
            WizardRunKind runKind, object[] customParams)
        {
            // Select entities template
            SelectEntitiesTemplate(false, string.Empty);

            // Place $parentwizardname$ in root dictionary
            RootWizard.RootDictionary[Constants.DictionaryEntries.ParentWizardName] = 
                Constants.ParentWizards.EntitiesWizard;

            // Place "$saferootprojectname$ in root dictionary.
            RootWizard.RootDictionary[Constants.DictionaryEntries.SafeRootProjectName] = 
                replacementsDictionary[Constants.DictionaryEntries.SafeProjectName];
        }

        public void BeforeOpeningFile(ProjectItem projectItem)
        {
        }

        public void ProjectFinishedGenerating(Project project)
        {
        }

        public void ProjectItemFinishedGenerating(ProjectItem projectItem)
        {
        }

        public void RunFinished()
        {
            // Delete parent of original destination directory
            // NOTE: The directory reappears after install has completed.
            var origDestDirectory = RootDictionary[Constants.DictionaryEntries.OriginalDestinationDirectory];
            var origParentDirectory = new DirectoryInfo(origDestDirectory).Parent;
            if (origParentDirectory != null) Directory.Delete(origParentDirectory.FullName);
        }

        public bool ShouldAddProjectItem(string filePath)
        {
            return true;
        }

        private static string GetEntitiesTemplateName(EntitiesSelection entitiesSelection)
        {
            if (entitiesSelection == EntitiesSelection.None)
                return null;

            if (entitiesSelection.HasFlag(EntitiesSelection.ClientService))
            {
                var clientSelection = string.Empty;
                if (entitiesSelection.HasFlag(EntitiesSelection.Portable))
                    clientSelection = Constants.EntitiesTemplates.ClientPortable;
                if (entitiesSelection.HasFlag(EntitiesSelection.DotNet45))
                    clientSelection = Constants.EntitiesTemplates.ClientNet45;
                return clientSelection + "|" + Constants.EntitiesTemplates.ServiceNet45;
            }

            if (entitiesSelection.HasFlag(EntitiesSelection.Service))
                return Constants.EntitiesTemplates.ServiceNet45;

            if (entitiesSelection.HasFlag(EntitiesSelection.Client))
            {
                if (entitiesSelection.HasFlag(EntitiesSelection.Portable))
                    return Constants.EntitiesTemplates.ClientPortable;
                if (entitiesSelection.HasFlag(EntitiesSelection.DotNet45))
                    return Constants.EntitiesTemplates.ClientNet45;
            }

            if (entitiesSelection.HasFlag(EntitiesSelection.Shared))
            {
                if (entitiesSelection.HasFlag(EntitiesSelection.Portable))
                    return Constants.EntitiesTemplates.SharedPortable;
                if (entitiesSelection.HasFlag(EntitiesSelection.DotNet45))
                    return Constants.EntitiesTemplates.SharedNet45;
            }
            return null;
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.ModelFirst/WebApiSample.Client.Entities.Temp/Location.cs<|end_filename|>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace WebApiSample.Client.Entities.Temp
{
    using System;
    using System.Collections.Generic;
    using TrackableEntities.Client;
    
    public partial class Location : EntityBase
    {
    
    	public string City
    	{ 
    		get { return _City; }
    		set
    		{
    			if (Equals(value, _City)) return;
    			_City = value;
    			NotifyPropertyChanged(() => City);
    		}
    	}
    	private string _City;
    
    	public string Country
    	{ 
    		get { return _Country; }
    		set
    		{
    			if (Equals(value, _Country)) return;
    			_Country = value;
    			NotifyPropertyChanged(() => Country);
    		}
    	}
    	private string _Country;
    }
}


<|start_filename|>Source/TrackableEntities.Client/ITrackingCollectionOfT.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.ComponentModel;

namespace TrackableEntities.Client
{
    /// <summary>
    /// Interface implemented by trackable collections.
    /// </summary>
    public interface ITrackingCollection<TEntity> : ICollection<TEntity>
        where TEntity : class, ITrackable, INotifyPropertyChanged
    {
        /// <summary>
        /// Get entities that have been marked as Added, Modified or Deleted.
        /// </summary>
        /// <returns>Collection containing only changed entities</returns>
        ChangeTrackingCollection<TEntity> GetChanges();
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Inheritance/SampleWebApi.Inheritance.WebApi/Areas/HelpPage/Views/Help/DisplayTemplates/SimpleTypeModelDescription.cshtml<|end_filename|>
@using SampleWebApi.Inheritance.WebApi.Areas.HelpPage.ModelDescriptions
@model SimpleTypeModelDescription
@Model.Documentation

<|start_filename|>Extensions/VS2015/Output/Extract/ProjectTemplates/TrackableWebApiPatterns/WebApi/App_Start/SimpleInjectorWebApiInitializer.cs<|end_filename|>
using System.Web.Http;
using SimpleInjector;
using SimpleInjector.Integration.WebApi;
using $safeprojectname$;
//using $saferootprojectname$.Service.EF.Contexts;
//using $saferootprojectname$.Service.EF.Repositories;
//using $saferootprojectname$.Service.EF.UnitsOfWork;
//using $saferootprojectname$.Service.Persistence.Repositories;
//using $saferootprojectname$.Service.Persistence.UnitsOfWork;

[assembly: WebActivator.PostApplicationStartMethod(typeof(SimpleInjectorWebApiInitializer), "Initialize")]

namespace $safeprojectname$
{
    public static class SimpleInjectorWebApiInitializer
    {
        public static void Initialize()
        {
            // Create IoC container
            var container = new Container();
  
            // Register dependencies
            InitializeContainer(container);
            container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
       
            // Verify registrations
            container.Verify();
            
            // Set Web API dependency resolver
            GlobalConfiguration.Configuration.DependencyResolver =
                new SimpleInjectorWebApiDependencyResolver(container);
        }
     
        private static void InitializeContainer(Container container)
        {
            // TODO: Register context, unit of work and repos with per request lifetime
            //container.RegisterWebApiRequest<INorthwindSlimContext, NorthwindSlimContext>();
            //container.RegisterWebApiRequest<INorthwindUnitOfWork, NorthwindUnitOfWork>();
            //container.RegisterWebApiRequest<ICustomerRepository, CustomerRepository>();
            //container.RegisterWebApiRequest<IOrderRepository, OrderRepository>();
        }
    }
}

<|start_filename|>Source/TrackableEntities.Client/ModelBase.cs<|end_filename|>
﻿using System;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.Serialization;

namespace TrackableEntities.Client
{
    /// <summary>
    /// Base class for model entities to support IIdentifiable and INotifyPropertyChanged
    /// </summary>
    /// <typeparam name="TModel">Entity type</typeparam>
    [Obsolete("ModelBase has been deprecated. Trackable entities should instead derive from EntityBase.")]
    [DataContract(IsReference = true)]
    public abstract class ModelBase<TModel> : IIdentifiable, INotifyPropertyChanged
    {
        /// <summary>
        /// Event for notification of property changes
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Fire PropertyChanged event.
        /// </summary>
        /// <typeparam name="TResult">Property return type</typeparam>
        /// <param name="property">Lambda expression for property</param>
        protected virtual void NotifyPropertyChanged<TResult>
            (Expression<Func<TModel, TResult>> property)
        {
            string propertyName = ((MemberExpression)property.Body).Member.Name;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        /// <summary>
        /// Identifier used for correlation with MergeChanges.
        /// </summary>
        [DataMember]
        public Guid EntityIdentifier
        {
            get
            {
                object identifier = GetEntityIdentifier(this);
                if (identifier is Guid)
                    return (Guid) identifier;
                return default(Guid);
            }
            set
            {
                SetEntityIdentifier(value);
            }
        }

        /// <summary>
        /// Generate entity identifier used for correlation with MergeChanges (if not yet done)
        /// </summary>
        public void SetEntityIdentifier()
        {
            if (GetEntityIdentifier(this).Equals(default(Guid)))
            {
                SetEntityIdentifier(this, Guid.NewGuid());
            }
        }

        /// <summary>
        /// Set entity identifier used for correlation with MergeChanges
        /// </summary>
        /// <param name="value">Identifier of some other entity</param>
        public void SetEntityIdentifier(Guid value)
        {
            SetEntityIdentifier(this, value);
        }

        /// <summary>
        /// Copy entity identifier used for correlation with MergeChanges from another entity
        /// </summary>
        /// <param name="other">Other trackable object</param>
        public void SetEntityIdentifier(IIdentifiable other)
        {
            SetEntityIdentifier(this, GetEntityIdentifier(other));
        }

        /// <summary>
        /// Indicates whether the current object is equal to another object of the same
        /// type. The comparison is based on EntityIdentifier.
        /// 
        /// If the local EntityIdentifier is empty, then return false.
        /// </summary>
        /// <param name="other">An object to compare with this object</param>
        public bool IsEquatable(IIdentifiable other)
        {
            var method = GetEquatableMethod(this);
            if (method != null)
            {
                return (bool)method.Invoke(this, new object[] { other });
            }
            return false;
        }

        /// <summary>
        /// Indicates whether the current object can be idenfitied with another object of the same type.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        bool IEquatable<IIdentifiable>.Equals(IIdentifiable other)
        {
            return IsEquatable(other);
        }

        private object GetEntityIdentifier(IIdentifiable entity)
        {
            var property = GetEntityIdentifierProperty(entity);

            if (property == null)
                return default(Guid);
            return (Guid)property.GetValue(entity, null);
        }

        private void SetEntityIdentifier(IIdentifiable entity, object identifier)
        {
            var property = GetEntityIdentifierProperty(entity);

            if (property != null)
                property.SetValue(entity, identifier, null);
        }

        private static MethodInfo GetEquatableMethod(object obj)
        {
            Type type = obj.GetType();
            string equatableMethod =
                Constants.EquatableMembers.EquatableMethodStart +
                type.FullName +
                Constants.EquatableMembers.EquatableMethodEnd;
            var method = PortableReflectionHelper.Instance.GetPrivateInstanceMethods(type)
                .SingleOrDefault(m => m.Name == equatableMethod);
            return method;
        }

        private static PropertyInfo GetEntityIdentifierProperty(object obj)
        {
            var property = obj.GetType().BaseTypes()
                .SelectMany(t => PortableReflectionHelper.Instance.GetPrivateInstanceProperties(t))
                .SingleOrDefault(p => p.Name == Constants.EquatableMembers.EntityIdentifierProperty);
            return property;
        }

        private static class Constants
        {
            /// <summary>
            /// Equatable member names.
            /// </summary>
            public static class EquatableMembers
            {
                /// <summary>Equatable method start</summary>
                public const string EquatableMethodStart = "System.IEquatable<";

                /// <summary>Equatable method end</summary>
                public const string EquatableMethodEnd = ">.Equals";

                /// <summary>Entity identifier property</summary>
                public const string EntityIdentifierProperty = "EntityIdentifier";
            }
        }
    }
}


<|start_filename|>Source/Tests/TrackableEntities.Client.Tests.Entities/NorthwindModels/Product.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace TrackableEntities.Client.Tests.Entities.NorthwindModels
{
    [JsonObject(IsReference = true)]
    public class Product : EntityBase
    {
        private int _productId;
        public int ProductId
        {
            get { return _productId; }
            set
            {
                if (value == _productId) return;
                _productId = value;
                NotifyPropertyChanged(() => ProductId);
            }
        }

        private string _productName;
        public string ProductName
        {
            get { return _productName; }
            set
            {
                if (value == _productName) return;
                _productName = value;
                NotifyPropertyChanged(() => ProductName);
            }
        }

        private decimal _unitPrice;
        public decimal UnitPrice
        {
            get { return _unitPrice; }
            set
            {
                if (value == _unitPrice) return;
                _unitPrice = value;
                NotifyPropertyChanged(() => UnitPrice);
            }
        }

        private bool _discontinued;
        public bool Discontinued
        {
            get { return _discontinued; }
            set
            {
                if (value == _discontinued) return;
                _discontinued = value;
                NotifyPropertyChanged(() => Discontinued);
            }
        }

        private int _categoryId;
        public int CategoryId
        {
            get { return _categoryId; }
            set
            {
                if (value == _categoryId) return;
                _categoryId = value;
                NotifyPropertyChanged(() => CategoryId);
            }
        }

        private Category _category;
        public Category Category
        {
            get { return _category; }
            set
            {
                if (value == _category) return;
                _category = value;
                CategoryChangeTracker = _category == null ? null
                    : new ChangeTrackingCollection<Category> { _category };
                NotifyPropertyChanged(() => Category);
            }
        }
        private ChangeTrackingCollection<Category> CategoryChangeTracker { get; set; }
    }
}


<|start_filename|>Extensions/Common/Wizards/TrackableEntities.ItemWizard/WcfServiceTypeWizard.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using EnvDTE;
using Microsoft.VisualStudio.TemplateWizard;

namespace TrackableEntities.ItemWizard
{
    public class WcfServiceTypeWizard : IWizard
    {
        public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, 
            WizardRunKind runKind, object[] customParams)
        {
            // Add custom parameters
            WizardHelper.AddCustomParameters(automationObject, replacementsDictionary,
                Dialogs.WcfServiceType.Title,
                Dialogs.WcfServiceType.Message, 
                Dialogs.WcfServiceType.GetDbContextName,
                Dialogs.WcfServiceType.DialogWidth);
        }

        public void BeforeOpeningFile(ProjectItem projectItem)
        {
        }

        public void ProjectFinishedGenerating(Project project)
        {
        }

        public void ProjectItemFinishedGenerating(ProjectItem projectItem)
        {
        }

        public void RunFinished()
        {
        }

        public bool ShouldAddProjectItem(string filePath)
        {
            return true;
        }
    }
}


<|start_filename|>Samples/VS2013/WcfSample/WcfSample.Service.Entities/Models/Mapping/CustomerMap.cs<|end_filename|>

using System.Data.Entity.ModelConfiguration;
using System.ComponentModel.DataAnnotations.Schema;

namespace WcfSample.Client.Entities.Models.Mapping
{
    public class CustomerMap : EntityTypeConfiguration<Customer>
    {
        public CustomerMap()
        {
            // Primary Key
            this.HasKey(t => t.CustomerId);

            // Properties
            this.Property(t => t.CustomerId)
                .IsRequired()
                .IsFixedLength()
                .HasMaxLength(5);

            this.Property(t => t.CompanyName)
                .IsRequired()
                .HasMaxLength(40);

            this.Property(t => t.ContactName)
                .HasMaxLength(30);

            this.Property(t => t.City)
                .HasMaxLength(15);

            this.Property(t => t.Country)
                .HasMaxLength(15);

            // Table & Column Mappings
            this.ToTable("Customer");
            this.Property(t => t.CustomerId).HasColumnName("CustomerId");
            this.Property(t => t.CompanyName).HasColumnName("CompanyName");
            this.Property(t => t.ContactName).HasColumnName("ContactName");
            this.Property(t => t.City).HasColumnName("City");
            this.Property(t => t.Country).HasColumnName("Country");

            // Tracking Properties
			this.Ignore(t => t.TrackingState);
			this.Ignore(t => t.ModifiedProperties);
			this.Ignore(t => t.EntityIdentifier);
        }
    }
}


<|start_filename|>Source/TrackableEntities.Patterns/IRepositoryAsync.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace TrackableEntities.Patterns
{
    /// <summary>
    /// Generic repository interface with basic asynchronous operations.
    /// </summary>
    /// <typeparam name="TEntity">Entity type</typeparam>
    public interface IRepositoryAsync<TEntity>
        where TEntity : class
    {
        /// <summary>
        /// Finds an entity with the given primary key values. If no entity is found, then null is returned.
        /// </summary>
        /// <param name="keyValues">The values of the primary key for the entity to be found.</param>
        /// <returns>A task that represents the asynchronous find operation. The task result contains the entity found, or null.</returns>
        Task<TEntity> FindAsync(params object[] keyValues);

        /// <summary>
        /// Finds an entity with the given primary key values. If no entity is found, then null is returned.
        /// </summary>
        /// <param name="cancellationToken">A CancellationToken to observe while waiting for the task to complete.</param>
        /// <param name="keyValues">The values of the primary key for the entity to be found.</param>
        /// <returns>A task that represents the asynchronous find operation. The task result contains the entity found, or null.</returns>
        Task<TEntity> FindAsync(CancellationToken cancellationToken, params object[] keyValues);

        /// <summary>
        /// Removes an entity from the respository.
        /// </summary>
        /// <param name="keyValues">The values of the primary key for the entity to be found.</param>
        /// <returns>A task that represents the asynchronous delete operation. The task result will be false if the entity does not exist in the repository, or true if successfully removed.</returns>
        Task<bool> DeleteAsync(params object[] keyValues);

        /// <summary>
        /// Removes an entity from the respository.
        /// </summary>
        /// <param name="cancellationToken">A CancellationToken to observe while waiting for the task to complete.</param>
        /// <param name="keyValues">The values of the primary key for the entity to be found.</param>
        /// <returns>A task that represents the asynchronous delete operation. The task result will be false if the entity does not exist in the repository, or true if successfully removed.</returns>
        Task<bool> DeleteAsync(CancellationToken cancellationToken, params object[] keyValues);

        /// <summary>
        /// Load related entities for an object graph.
        /// </summary>
        /// <param name="entity">Entity on which related entities are loaded.</param>
        /// <returns>A task that represents the asynchronous delete operation. The task result will be false if the entity does not exist in the repository, or true if successfully removed.</returns>
        Task LoadRelatedEntitiesAsync(TEntity entity);

        /// <summary>
        /// Load related entities for an object graph.
        /// </summary>
        /// <param name="entity">Entity on which related entities are loaded.</param>
        /// <param name="cancellationToken">A CancellationToken to observe while waiting for the task to complete.</param>
        /// <returns>A task that represents the asynchronous delete operation. The task result will be false if the entity does not exist in the repository, or true if successfully removed.</returns>
        Task LoadRelatedEntitiesAsync(TEntity entity, CancellationToken cancellationToken);

        /// <summary>
        /// Load related entities for more than one object graph.
        /// </summary>
        /// <param name="entities">Entities on which related entities are loaded.</param>
        /// <returns>A task that represents the asynchronous delete operation. The task result will be false if the entity does not exist in the repository, or true if successfully removed.</returns>
        Task LoadRelatedEntitiesAsync(IEnumerable<TEntity> entities);

        /// <summary>
        /// Load related entities for more than one object graph.
        /// </summary>
        /// <param name="entities">Entities on which related entities are loaded.</param>
        /// <param name="cancellationToken">A CancellationToken to observe while waiting for the task to complete.</param>
        /// <returns>A task that represents the asynchronous delete operation. The task result will be false if the entity does not exist in the repository, or true if successfully removed.</returns>
        Task LoadRelatedEntitiesAsync(IEnumerable<TEntity> entities, CancellationToken cancellationToken);
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm/WebApiSample.Mvvm.Service.Entities/Models/Employee.cs<|end_filename|>
using System;
using System.Collections.Generic;
using TrackableEntities;

namespace WebApiSample.Mvvm.Service.Entities.Models
{
    public partial class Employee : ITrackable, IMergeable
    {
        public Employee()
        {
            this.Territories = new List<Territory>();
        }

        public int EmployeeId { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public Nullable<System.DateTime> BirthDate { get; set; }
        public Nullable<System.DateTime> HireDate { get; set; }
        public string City { get; set; }
        public string Country { get; set; }
        public List<Territory> Territories { get; set; }

        public TrackingState TrackingState { get; set; }
        public ICollection<string> ModifiedProperties { get; set; }
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Source/TrackableEntities.Patterns/IUnitOfWork.cs<|end_filename|>
﻿using System;
using System.Threading.Tasks;

namespace TrackableEntities.Patterns
{
    /// <summary>
    /// Unit of work for committing changes across one or more repositories.
    /// </summary>
    public interface IUnitOfWork
    {
        /// <summary>
        /// Saves changes made to one or more repositories.
        /// </summary>
        /// <returns>The number of objects saved.</returns>
        int SaveChanges();
    }
}


<|start_filename|>Source/Tests/TrackableEntities.Client.Tests.Entities/NorthwindModels/Customer.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace TrackableEntities.Client.Tests.Entities.NorthwindModels
{
    [JsonObject(IsReference = true)]
    public class Customer : EntityBase, IRefPropertyChangeTrackerResolver
    {
        private string _customerId;
        public string CustomerId
        {
            get { return _customerId; }
            set
            {
                if (value == _customerId) return;
                _customerId = value;
                NotifyPropertyChanged(() => CustomerId);
            }
        }

        private string _customerName;
        public string CustomerName
        {
            get { return _customerName; }
            set
            {
                if (value == _customerName) return;
                _customerName = value;
                NotifyPropertyChanged(() => CustomerName);
            }
        }

        private string _data;
        public string Data
        {
            get { return _data; }
            set
            {
                if (value == _data) return;
                _data = value;
                NotifyPropertyChanged(() => Data);
            }
        }

        private string _territoryId;
        public string TerritoryId
        {
            get { return _territoryId; }
            set
            {
                _territoryId = value;
                NotifyPropertyChanged(() => TerritoryId);
            }
        }

        private CustomerSetting _customerSetting;
        public CustomerSetting CustomerSetting
        {
            get { return _customerSetting; }
            set
            {
                if (value == _customerSetting) return;
                _customerSetting = value;
                Xxx.CustomerSettingChangeTracker = _customerSetting == null ? null
                    : new ChangeTrackingCollection<CustomerSetting> { _customerSetting };
                NotifyPropertyChanged(() => CustomerSetting);
            }
        }
        private struct NON_STANDARD_LOCATION
        {
            internal ChangeTrackingCollection<CustomerSetting> CustomerSettingChangeTracker { get; set; }
        }
        private NON_STANDARD_LOCATION Xxx;

        private Territory _territory;
        public Territory Territory
        {
            get { return _territory; }
            set
            {
                if (value == _territory) return;
                _territory = value;
                TerritoryChangeTracker = _territory == null ? null
                    : new ChangeTrackingCollection<Territory> { _territory };
            }
        }
        private ChangeTrackingCollection<Territory> TerritoryChangeTracker { get; set; }

        ITrackingCollection IRefPropertyChangeTrackerResolver.GetRefPropertyChangeTracker(string propertyName)
        {
            if (propertyName == "CustomerSetting")
                return Xxx.CustomerSettingChangeTracker;
            if (propertyName == "Territory")
                return TerritoryChangeTracker;
            return null;
        }
    }
}


<|start_filename|>Source/TrackableEntities.EF.5/Exceptions/RelationshipNotDeterminedException.cs<|end_filename|>
#if EF_6
namespace TrackableEntities.EF6.Exceptions
#else
namespace TrackableEntities.EF5.Exceptions
#endif
{
    /// <summary>
    /// Exception for state when the relationship cannot be determined for a given type and a givven property.
    /// </summary>
    public class RelationshipNotDeterminedException : TrackableEntitiesException
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="T:RelationshipNotDeterminedException"/> class with a specified error message.
        /// </summary>
        /// <param name="message">A message that describes the error </param>
        public RelationshipNotDeterminedException(string message)
            : base(message)
        {
        }        
    }
}

<|start_filename|>Extensions/Common/Wizards/TrackableEntities.TemplateWizard/ChildWizard.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.IO;
using System.Windows.Forms;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.TemplateWizard;
using NuGet.VisualStudio;

namespace TrackableEntities.TemplateWizard
{
    public class ChildWizard : IWizard
    {
        [Import]
        internal IVsTemplateWizard Wizard { get; set; }

        protected DTE2 Dte2;

        // Retrieve global replacement parameters
        public void RunStarted(object automationObject,
            Dictionary<string, string> replacementsDictionary,
            WizardRunKind runKind, object[] customParams)
        {
            // Add custom parameters
            replacementsDictionary.Add(Constants.DictionaryEntries.SafeRootProjectName,
                RootWizard.RootDictionary[Constants.DictionaryEntries.SafeRootProjectName]);
            replacementsDictionary.Add(Constants.DictionaryEntries.ClientEntitiesTemplate,
                RootWizard.RootDictionary[Constants.DictionaryEntries.ClientEntitiesTemplate]);
            replacementsDictionary.Add(Constants.DictionaryEntries.ServiceEntitiesTemplate,
                RootWizard.RootDictionary[Constants.DictionaryEntries.ServiceEntitiesTemplate]);

            // Process entities template
            var templateName = Path.GetFileNameWithoutExtension((string)customParams[0]);
            ProcessEntitiesTemplate(replacementsDictionary, templateName);

            // Get DTE
            Dte2 = (DTE2)automationObject;

            // Init NuGet Wizard
            Initialize(automationObject);
            Wizard.RunStarted(automationObject, replacementsDictionary, runKind, customParams);
        }

        public void BeforeOpeningFile(ProjectItem projectItem)
        {
        }

        public void ProjectFinishedGenerating(Project project)
        {
            MoveGeneratedProject(ref project);
            Wizard.ProjectFinishedGenerating(project);
        }

        public void ProjectItemFinishedGenerating(ProjectItem projectItem)
        {
        }

        public void RunFinished()
        {
        }

        public bool ShouldAddProjectItem(string filePath)
        {
            return true;
        }

        protected virtual void ProcessEntitiesTemplate(
            Dictionary<string, string> replacementsDictionary, string templateName)
        {            
        }

        protected virtual void MoveGeneratedProject(ref Project project)
        {
        }

        private void Initialize(object automationObject)
        {
            using (var provider = new ServiceProvider((IServiceProvider)automationObject))
            {
                var service = (IComponentModel)provider.GetService(typeof(SComponentModel));
                using (var container = new CompositionContainer(service.DefaultExportProvider))
                {
                    container.ComposeParts(this);
                }
            }
            if (Wizard == null)
            {
                MessageBox.Show("NuGet Package Manager not available.");
                throw new WizardBackoutException("NuGet Package Manager not available.");
            }
        }
    }
}


<|start_filename|>Build/Scripts/Debug/TrackableEntities.Patterns-test.cmd<|end_filename|>
cd ..\..\..\
set PackageVersion=2.5.0-test
rem pass 1 to debug, 0 to run without pausing
Build\Scripts\TrackableEntities.Patterns.cmd 1


<|start_filename|>Samples/VS2013/WebApiSample.Patterns/WebApiSample.Service.EF/Contexts/NorthwindSlimContext.cs<|end_filename|>
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using WebApiSample.Service.EF.Mapping;
using WebApiSample.Service.Entities.Models;

namespace WebApiSample.Service.EF.Contexts
{
    public partial class NorthwindSlimContext : DbContext, INorthwindSlimContext
    {
        static NorthwindSlimContext()
        {
            Database.SetInitializer(new NorthwindSlimDatabaseInitializer());
        }

        public NorthwindSlimContext()
            : base("Name=NorthwindSlimContext")
        {
            this.Configuration.LazyLoadingEnabled = false;
            this.Configuration.ProxyCreationEnabled = false;
        }

        public IDbSet<Category> Categories { get; set; }
        public IDbSet<Customer> Customers { get; set; }
        public IDbSet<CustomerSetting> CustomerSettings { get; set; }
        public IDbSet<Order> Orders { get; set; }
        public IDbSet<OrderDetail> OrderDetails { get; set; }
        public IDbSet<Product> Products { get; set; }
        public IDbSet<Employee> Employees { get; set; }
        public IDbSet<Territory> Territories { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new CategoryMap());
            modelBuilder.Configurations.Add(new CustomerMap());
            modelBuilder.Configurations.Add(new CustomerSettingMap());
            modelBuilder.Configurations.Add(new OrderMap());
            modelBuilder.Configurations.Add(new OrderDetailMap());
            modelBuilder.Configurations.Add(new ProductMap());
            modelBuilder.Configurations.Add(new EmployeeMap());
            modelBuilder.Configurations.Add(new TerritoryMap());

            modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
        }
    }
}


<|start_filename|>Extensions/Common/Wizards/TemplateWizard.Service.Entities/Models/Category.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using TrackableEntities;

namespace TemplateWizard.Service.Entities.Models
{
    [JsonObject(IsReference = true)]
    [DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
    public partial class Category : ITrackable
    {
        public Category()
        {
            this.Products = new List<Product>();
        }

        [DataMember]
        public int CategoryId { get; set; }
        [DataMember]
        public string CategoryName { get; set; }
        [DataMember]
        public List<Product> Products { get; set; }

        [DataMember]
        public TrackingState TrackingState { get; set; }
        [DataMember]
        public ICollection<string> ModifiedProperties { get; set; }
    }
}


<|start_filename|>Extensions/Common/Wizards/TemplateWizard.Service.Entities/Models/Product.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using TrackableEntities;

namespace TemplateWizard.Service.Entities.Models
{
    [JsonObject(IsReference = true)]
    [DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
    public partial class Product : ITrackable
    {
        public Product()
        {
            this.OrderDetails = new List<OrderDetail>();
        }

        [DataMember]
        public int ProductId { get; set; }
        [DataMember]
        public string ProductName { get; set; }
        [DataMember]
        public Nullable<int> CategoryId { get; set; }
        [DataMember]
        public Nullable<decimal> UnitPrice { get; set; }
        [DataMember]
        public bool Discontinued { get; set; }
        [DataMember]
        public byte[] RowVersion { get; set; }
        [DataMember]
        public Category Category { get; set; }
        [DataMember]
        public List<OrderDetail> OrderDetails { get; set; }

        [DataMember]
        public TrackingState TrackingState { get; set; }
        [DataMember]
        public ICollection<string> ModifiedProperties { get; set; }
    }
}


<|start_filename|>Extensions/VS2012/Output/Item Templates/Extract/WebApiController/WebApiController.cs<|end_filename|>
﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Description;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using TrackableEntities;
using TrackableEntities.EF5;
using TrackableEntities.Common;
using $entitiesNamespace$;

// NOTE: Primary key name and/or type may need to be set manually.

namespace $rootnamespace$
{
	public class $safeitemname$ : ApiController
	{
        private readonly $dbContextName$ _dbContext = new $dbContextName$();

		// GET api/$entityName$
        public IEnumerable<$entityName$> Get$entitySetName$()
        {
            IEnumerable<$entityName$> entities = _dbContext.$entitySetName$
			    // TODO: Add Includes for reference and/or collection properties
				.ToList();

            return entities;
        }

        // GET api/$entityName$/5
        public $entityName$ Get$entityName$(int id)
        {
            $entityName$ entity = _dbContext.$entitySetName$
			    // TODO: Add Includes for reference and/or collection properties
                .SingleOrDefault(e => e.$entityName$Id == id);

            if (entity == null)
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
            }

            return entity;
        }

        // POST api/$entityName$
        public HttpResponseMessage Post$entityName$($entityName$ entity)
        {
            if (!ModelState.IsValid)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }

            entity.TrackingState = TrackingState.Added;
            _dbContext.ApplyChanges(entity);

            try
            {
                _dbContext.SaveChanges();
            }
            catch (DbUpdateException ex)
            {
                if (_dbContext.$entitySetName$.Any(e => e.$entityName$Id == entity.$entityName$Id))
                {
	                return Request.CreateErrorResponse(HttpStatusCode.Conflict, ex);
                }
                throw;
            }

            _dbContext.LoadRelatedEntities(entity);
            entity.AcceptChanges();

            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, entity);
            response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = entity.$entityName$Id }));
            return response;
        }

        // PUT api/$entityName$
        public HttpResponseMessage Put$entityName$($entityName$ entity)
        {
            if (!ModelState.IsValid)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }

            _dbContext.ApplyChanges(entity);

            try
            {
                _dbContext.SaveChanges();
            }
            catch (DbUpdateConcurrencyException ex)
            {
                if (!_dbContext.$entitySetName$.Any(e => e.$entityName$Id == entity.$entityName$Id))
                {
	                return Request.CreateErrorResponse(HttpStatusCode.Conflict, ex);
                }
                throw;
            }

			_dbContext.LoadRelatedEntities(entity);
			entity.AcceptChanges();

            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, entity);
            return response;
        }

        // DELETE api/$entityName$/5
        public HttpResponseMessage Delete$entityName$(int id)
        {
            $entityName$ entity = _dbContext.$entitySetName$
			    // TODO: Include child entities if any
                .SingleOrDefault(e => e.$entityName$Id == id);
            if (entity == null)
            {
                return Request.CreateResponse(HttpStatusCode.OK);
            }

			entity.TrackingState = TrackingState.Deleted;
			_dbContext.ApplyChanges(entity);

            try
            {
                _dbContext.SaveChanges();
            }
            catch (DbUpdateConcurrencyException ex)
            {
                if (!_dbContext.$entitySetName$.Any(e => e.$entityName$Id == entity.$entityName$Id))
                {
	                return Request.CreateErrorResponse(HttpStatusCode.Conflict, ex);
                }
                throw;
            }

            return Request.CreateResponse(HttpStatusCode.OK);
        }

        protected override void Dispose(bool disposing)
        {
            _dbContext.Dispose();
            base.Dispose(disposing);
        }
    }
}


<|start_filename|>Source/Tests/TrackableEntities.EF.5.Tests/CreateDbOptions.cs<|end_filename|>
﻿using System;

namespace TrackableEntities.EF.Tests
{
    public enum CreateDbOptions
    {
        CreateDatabaseIfNotExists,
        DropCreateDatabaseAlways,
        DropCreateDatabaseIfModelChanges,
        DropCreateDatabaseSeed
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.ModelFirst/WebApiSample.Service.Entities/Category.cs<|end_filename|>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace WebApiSample.Service.Entities
{
    using System;
    using System.Collections.Generic;
    using TrackableEntities;
    
    public partial class Category : ITrackable, IMergeable
    {
        public Category()
        {
            this.Products = new List<Product>();
        }
    
        public int CategoryId { get; set; }
        public string CategoryName { get; set; }
    
        public ICollection<Product> Products { get; set; }
    
        public TrackingState TrackingState { get; set; }
        public ICollection<string> ModifiedProperties { get; set; }
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Extensions/VS2015/Output/Extract/ProjectTemplates/TrackableWcfService/ConsoleClient/Program.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using TrackableEntities.Client;
//using $saferootprojectname$.Entities.Models;

// This is an example which retrieves customers and orders from the Northwind
// sample database. You should alter the code based on your own database schema.

namespace $safeprojectname$
{
    class Program
    {
        static void Main(string[] args)
        {
            /* // Main method
            
            Console.WriteLine("Press Enter to start");
            Console.ReadLine();

            ICustomerService customerService = new ChannelFactory<ICustomerService>("customerService").CreateChannel();
            IOrderService orderService = new ChannelFactory<IOrderService>("orderService").CreateChannel();

            using ((IDisposable)customerService)
            using ((IDisposable)orderService)
            {
                try
                {
                    // Get customers
                    Console.WriteLine("Customers:");
                    IEnumerable<Customer> customers = customerService.GetCustomersAsync().Result;
                    if (customers == null) return;
                    foreach (var c in customers)
                        PrintCustomer(c);

                    // Get orders for a customer
                    Console.WriteLine("\nGet customer orders {CustomerId}:");
                    string customerId = Console.ReadLine();
                    if (!customers.Any(c => string.Equals(c.CustomerId, customerId, StringComparison.OrdinalIgnoreCase)))
                    {
                        Console.WriteLine("Invalid customer id: {0}", customerId.ToUpper());
                        return;
                    }
                    IEnumerable<Order> orders = orderService.GetCustomerOrdersAsync(customerId).Result;
                    foreach (var o in orders)
                        PrintOrder(o);

                    // Get an order
                    Console.WriteLine("\nGet an order {OrderId}:");
                    int orderId = int.Parse(Console.ReadLine());
                    if (!orders.Any(o => o.OrderId == orderId))
                    {
                        Console.WriteLine("Invalid order id: {0}", orderId);
                        return;
                    }
                    Order order = orderService.GetOrderAsync(orderId).Result;
                    PrintOrderWithDetails(order);

                    // Create a new order
                    Console.WriteLine("\nPress Enter to create a new order for {0}",
                        customerId.ToUpper());
                    Console.ReadLine();

                    var newOrder = new Order
                    {
                        CustomerId = customerId,
                        OrderDate = DateTime.Today,
                        ShippedDate = DateTime.Today.AddDays(1),
                        OrderDetails = new ChangeTrackingCollection<OrderDetail>
                            {
                                new OrderDetail { ProductId = 1, Quantity = 5, UnitPrice = 10 },
                                new OrderDetail { ProductId = 2, Quantity = 10, UnitPrice = 20 },
                                new OrderDetail { ProductId = 4, Quantity = 40, UnitPrice = 40 }
                            }
                    };
                    var createdOrder = orderService.CreateOrderAsync(newOrder).Result;
                    PrintOrderWithDetails(createdOrder);

                    // Update the order
                    Console.WriteLine("\nPress Enter to update order details");
                    Console.ReadLine();

                    // Start change-tracking the order
                    var changeTracker = new ChangeTrackingCollection<Order>(createdOrder);

                    // Modify order details
                    createdOrder.OrderDetails[0].UnitPrice++;
                    createdOrder.OrderDetails.RemoveAt(1);
                    createdOrder.OrderDetails.Add(new OrderDetail
                    {
                        OrderId = createdOrder.OrderId,
                        ProductId = 3,
                        Quantity = 15,
                        UnitPrice = 30
                    });

                    // Submit changes
                    Order changedOrder = changeTracker.GetChanges().SingleOrDefault();
                    Order updatedOrder = orderService.UpdateOrderAsync(changedOrder).Result;

                    // Merge changes
                    changeTracker.MergeChanges(updatedOrder);
                    Console.WriteLine("Updated order:");
                    PrintOrderWithDetails(createdOrder);

                    // Delete the order
                    Console.WriteLine("\nPress Enter to delete the order");
                    Console.ReadLine();
                    bool deleted = orderService.DeleteOrderAsync(createdOrder.OrderId).Result;

                    // Verify order was deleted
                    Order deletedOrder = orderService.GetOrderAsync(createdOrder.OrderId).Result;
                    Console.WriteLine(deleted && deletedOrder == null
                        ? "Order was successfully deleted"
                        : "Order was not deleted");
                }
                catch (AggregateException aggEx)
                {
                    var baseEx = aggEx.Flatten().GetBaseException();
                    var innerExMsg = baseEx.InnerException != null ? "\r\n" + baseEx.InnerException.Message : "";
                    Console.WriteLine(baseEx.Message + innerExMsg);
                }
                finally
                {
                    var channel = customerService as IClientChannel;
                    if (channel != null && channel.State == CommunicationState.Faulted)
                    {
                        channel.Abort();
                    }
                }

                // Keep console open
                Console.WriteLine("Press any key to exit");
                Console.ReadKey(true);
            }
            */
        }

        /* // Helper methods
        
        private static void PrintCustomer(Customer c)
        {
            Console.WriteLine("{0} {1} {2} {3}",
                c.CustomerId,
                c.CompanyName,
                c.ContactName,
                c.City);
        }

        private static void PrintOrder(Order o)
        {
            Console.WriteLine("{0} {1}",
                o.OrderId,
                o.OrderDate.GetValueOrDefault().ToShortDateString());
        }

        private static void PrintOrderWithDetails(Order o)
        {
            Console.WriteLine("{0} {1}",
                o.OrderId,
                o.OrderDate.GetValueOrDefault().ToShortDateString());
            foreach (var od in o.OrderDetails)
            {
                Console.WriteLine("\t{0} {1} {2} {3}",
                    od.OrderDetailId,
                    od.Product.ProductName,
                    od.Quantity,
                    od.UnitPrice.ToString("c"));
            }
        }
        */
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.ModelFirst/WebApiSample.Client.Entities.Temp/Customer.cs<|end_filename|>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace WebApiSample.Client.Entities.Temp
{
    using System;
    using System.Collections.Generic;
    using TrackableEntities.Client;
    
    public partial class Customer : EntityBase
    {
        public Customer()
        {
            this.Orders = new ChangeTrackingCollection<Order>();
            this.Location = new Location();
        }
        
    	public string CustomerId
    	{ 
    		get { return _CustomerId; }
    		set
    		{
    			if (Equals(value, _CustomerId)) return;
    			_CustomerId = value;
    			NotifyPropertyChanged(() => CustomerId);
    		}
    	}
    	private string _CustomerId;
        
    	public string CompanyName
    	{ 
    		get { return _CompanyName; }
    		set
    		{
    			if (Equals(value, _CompanyName)) return;
    			_CompanyName = value;
    			NotifyPropertyChanged(() => CompanyName);
    		}
    	}
    	private string _CompanyName;
        
    	public string ContactName
    	{ 
    		get { return _ContactName; }
    		set
    		{
    			if (Equals(value, _ContactName)) return;
    			_ContactName = value;
    			NotifyPropertyChanged(() => ContactName);
    		}
    	}
    	private string _ContactName;
    
    
    	public Location Location
    	{ 
    		get { return _Location; }
    		set
    		{
    			if (Equals(value, _Location)) return;
    			_Location = value;
    			NotifyPropertyChanged(() => Location);
    		}
    	}
    	private Location _Location;
    
    	public CustomerSetting CustomerSetting
    	{
    		get { return _CustomerSetting; }
    		set
    		{
    			if (Equals(value, _CustomerSetting)) return;
    			_CustomerSetting = value;
    			CustomerSettingChangeTracker = _CustomerSetting == null ? null
    				: new ChangeTrackingCollection<CustomerSetting> { _CustomerSetting };
    			NotifyPropertyChanged(() => CustomerSetting);
    		}
    	}
    	private CustomerSetting _CustomerSetting;
    	private ChangeTrackingCollection<CustomerSetting> CustomerSettingChangeTracker { get; set; }
    
    	public ChangeTrackingCollection<Order> Orders
    	{
    		get { return _Orders; }
    		set
    		{
    			if (Equals(value, _Orders)) return;
    			_Orders = value;
    			NotifyPropertyChanged(() => Orders);
    		}
    	}
    	private ChangeTrackingCollection<Order> _Orders;
    }
}


<|start_filename|>Source/Tests/TrackableEntities.EF.5.Tests/NorthwindModels/ProductInfo.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TrackableEntities.EF.Tests.NorthwindModels
{
    public partial class ProductInfo : ITrackable
    {
        [Key, Column(Order = 1)]
        public int ProductInfoKey1 { get; set; }
        [Key, Column(Order = 2)]
        public int ProductInfoKey2 { get; set; }

        public string Info { get; set; }

        [NotMapped]
        public TrackingState TrackingState { get; set; }
        [NotMapped]
        public ICollection<string> ModifiedProperties { get; set; }
    }
}


<|start_filename|>Samples/VS2012/WebApiSample/WebApiSample.Client.Entities/Models/Order.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using TrackableEntities;
using TrackableEntities.Client;

namespace WebApiSample.Client.Entities.Models
{
    [JsonObject(IsReference = true)]
    [DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
    public partial class Order : ModelBase<Order>, IEquatable<Order>, ITrackable
    {
		public Order()
		{
			this.OrderDetails = new ChangeTrackingCollection<OrderDetail>();
		}

		[DataMember]
		public int OrderId
		{ 
			get { return _OrderId; }
			set
			{
				if (Equals(value, _OrderId)) return;
				_OrderId = value;
				NotifyPropertyChanged(m => m.OrderId);
			}
		}
		private int _OrderId;

		[DataMember]
		public string CustomerId
		{ 
			get { return _CustomerId; }
			set
			{
				if (Equals(value, _CustomerId)) return;
				_CustomerId = value;
				NotifyPropertyChanged(m => m.CustomerId);
			}
		}
		private string _CustomerId;

		[DataMember]
		public Nullable<System.DateTime> OrderDate
		{ 
			get { return _OrderDate; }
			set
			{
				if (Equals(value, _OrderDate)) return;
				_OrderDate = value;
				NotifyPropertyChanged(m => m.OrderDate);
			}
		}
		private Nullable<System.DateTime> _OrderDate;

		[DataMember]
		public Nullable<System.DateTime> ShippedDate
		{ 
			get { return _ShippedDate; }
			set
			{
				if (Equals(value, _ShippedDate)) return;
				_ShippedDate = value;
				NotifyPropertyChanged(m => m.ShippedDate);
			}
		}
		private Nullable<System.DateTime> _ShippedDate;

		[DataMember]
		public Nullable<int> ShipVia
		{ 
			get { return _ShipVia; }
			set
			{
				if (Equals(value, _ShipVia)) return;
				_ShipVia = value;
				NotifyPropertyChanged(m => m.ShipVia);
			}
		}
		private Nullable<int> _ShipVia;

		[DataMember]
		public Nullable<decimal> Freight
		{ 
			get { return _Freight; }
			set
			{
				if (Equals(value, _Freight)) return;
				_Freight = value;
				NotifyPropertyChanged(m => m.Freight);
			}
		}
		private Nullable<decimal> _Freight;

		[DataMember]
		public Customer Customer
		{
			get { return _Customer; }
			set
			{
				if (Equals(value, _Customer)) return;
				_Customer = value;
				CustomerChangeTracker = _Customer == null ? null
					: new ChangeTrackingCollection<Customer> { _Customer };
				NotifyPropertyChanged(m => m.Customer);
			}
		}
		private Customer _Customer;
		private ChangeTrackingCollection<Customer> CustomerChangeTracker { get; set; }

		[DataMember]
		public ChangeTrackingCollection<OrderDetail> OrderDetails
		{
			get { return _OrderDetails; }
			set
			{
				if (Equals(value, _OrderDetails)) return;
				_OrderDetails = value;
				NotifyPropertyChanged(m => m.OrderDetails);
			}
		}
		private ChangeTrackingCollection<OrderDetail> _OrderDetails;

        #region Change Tracking

		[DataMember]
		public TrackingState TrackingState { get; set; }

		[DataMember]
		public ICollection<string> ModifiedProperties { get; set; }

		[JsonProperty, DataMember]
		private Guid EntityIdentifier { get; set; }

		#pragma warning disable 414

		[JsonProperty, DataMember]
		private Guid _entityIdentity = default(Guid);

		#pragma warning restore 414

		bool IEquatable<Order>.Equals(Order other)
		{
			if (EntityIdentifier != default(Guid))
				return EntityIdentifier == other.EntityIdentifier;
			return false;
		}
        #endregion
	}
}


<|start_filename|>Source/Tests/TrackableEntities.Client.Tests/ChangeTrackingCollectionWithChildrenTests.cs<|end_filename|>
﻿using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using TrackableEntities.Client.Tests.Entities.FamilyModels;
using TrackableEntities.Client.Tests.Entities.Mocks;
using TrackableEntities.Client.Tests.Entities.NorthwindModels;
using Xunit;

namespace TrackableEntities.Client.Tests
{
    public class ChangeTrackingCollectionWithChildrenTests
    {
        #region Set Status Tests

        [Fact]
        public void Existing_Parent_With_Children_Should_Have_Children_Marked()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var orderDetails = (IList<OrderDetail>)changeTracker[0].OrderDetails;
            var addedDetail = new OrderDetail
                {
                    ProductId = 1,
                    Product = database.Products[0],
                    Quantity = 10,
                    UnitPrice = 20M
                };
            var modifiedDetail = orderDetails[0];
            var deletedDetail = orderDetails[1];
            addedDetail.Order = order;
            modifiedDetail.Order = order;
            deletedDetail.Order = order;

            // Act
            modifiedDetail.UnitPrice++;
            orderDetails.Remove(deletedDetail);
            orderDetails.Add(addedDetail);

            // Assert
            Assert.Equal(TrackingState.Added, addedDetail.TrackingState);
            Assert.Equal(TrackingState.Modified, modifiedDetail.TrackingState);
            Assert.Equal(TrackingState.Deleted, deletedDetail.TrackingState);
        }

        [Fact]
        public void Existing_Parent_With_Added_Children_Should_Have_Children_Marked_As_Added()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var orderDetails = (IList<OrderDetail>)changeTracker[0].OrderDetails;
            var addedDetail1 = new OrderDetail
            {
                ProductId = 1,
                Product = database.Products[0],
                Quantity = 10,
                UnitPrice = 20M
            };
            var addedDetail2 = new OrderDetail
            {
                ProductId = 2,
                Product = database.Products[1],
                Quantity = 20,
                UnitPrice = 30M
            };

            // Act
            orderDetails.Add(addedDetail1);
            orderDetails.Add(addedDetail2);

            // Assert
            Assert.Equal(TrackingState.Added, addedDetail1.TrackingState);
            Assert.Equal(TrackingState.Added, addedDetail2.TrackingState);
        }

        [Fact]
        public void Added_Parent_With_Children_Should_Have_Children_Marked_As_Added()
        {
            // Arrange
            var database = new MockNorthwind();
            var changeTracker = new ChangeTrackingCollection<Order>(true);
            var order = database.Orders[0];
            var orderDetails = (IList<OrderDetail>)order.OrderDetails;

            // Act
            changeTracker.Add(order);

            // Assert
            Assert.Equal(TrackingState.Added, order.TrackingState);
            Assert.Equal(TrackingState.Added, orderDetails[0].TrackingState);
        }

        [Fact]
        public void Added_Parent_With_Modified_Children_Should_Have_Children_Marked_As_Added()
        {
            // Arrange
            var database = new MockNorthwind();
            var changeTracker = new ChangeTrackingCollection<Order>(true);
            var order = database.Orders[0];
            var orderDetails = (IList<OrderDetail>)order.OrderDetails;

            // Act
            changeTracker.Add(order);
            orderDetails[0].Quantity++;

            // Assert
            Assert.Equal(TrackingState.Added, order.TrackingState);
            Assert.Equal(TrackingState.Added, orderDetails[0].TrackingState);
        }

        [Fact]
        public void Added_Parent_Then_Removed_Should_Have_Children_Marked_As_Unchanged()
        {
            // Arrange
            var database = new MockNorthwind();
            var changeTracker = new ChangeTrackingCollection<Order>(true);
            var order = database.Orders[0];
            var orderDetails = (IList<OrderDetail>)order.OrderDetails;
            var orderDetail = orderDetails[0];

            // Act
            changeTracker.Add(order);
            changeTracker.Remove(order);

            // Assert
            Assert.Equal(TrackingState.Unchanged, order.TrackingState);
            Assert.Equal(TrackingState.Unchanged, orderDetail.TrackingState);
        }

        [Fact]
        public void Added_Parent_With_Removed_Children_Should_Have_Children_Marked_As_Unchanged()
        {
            // Arrange
            var database = new MockNorthwind();
            var changeTracker = new ChangeTrackingCollection<Order>(true);
            var order = database.Orders[0];
            var orderDetails = (IList<OrderDetail>)order.OrderDetails;
            var orderDetail = orderDetails[0];

            // Act
            changeTracker.Add(order);
            order.OrderDetails.Remove(orderDetail);

            // Assert
            Assert.Equal(TrackingState.Added, order.TrackingState);
            Assert.Equal(TrackingState.Unchanged, orderDetail.TrackingState);
        }

        [Fact]
        public void Existing_Parent_Removed_With_Modified_Children_Should_Have_Children_Marked_As_Deleted()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var orderDetails = (IList<OrderDetail>)order.OrderDetails;
            var orderDetail = orderDetails[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            orderDetail.Quantity++;

            // Act
            changeTracker.Remove(order);

            // Assert
            Assert.Equal(TrackingState.Deleted, order.TrackingState);
            Assert.Equal(TrackingState.Deleted, orderDetail.TrackingState);
        }

        #endregion

        #region Modified Properties Tests

        [Fact]
        public void Existing_Parent_With_Modified_Children_Should_Add_ModifiedProperties()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var orderDetails = (IList<OrderDetail>)changeTracker[0].OrderDetails;
            var modifiedDetail = orderDetails[0];

            // Act
            modifiedDetail.UnitPrice++;

            // Assert
            Assert.Contains("UnitPrice", modifiedDetail.ModifiedProperties);
        }

        [Fact]
        public void Existing_Parent_With_Modified_Children_Should_Add_Multiple_ModifiedProperties()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var orderDetails = (IList<OrderDetail>)changeTracker[0].OrderDetails;
            var modifiedDetail = orderDetails[0];

            // Act
            modifiedDetail.Quantity++;
            modifiedDetail.UnitPrice++;

            // Assert
            Assert.Contains("Quantity", modifiedDetail.ModifiedProperties);
            Assert.Contains("UnitPrice", modifiedDetail.ModifiedProperties);
        }

        [Fact]
        public void Existing_Parent_With_Excluded_Children_Should_Not_Be_Marked_As_Modified()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var orderDetails = changeTracker[0].OrderDetails;
            orderDetails.ExcludedProperties.Add("Quantity");
            var modifiedDetail = orderDetails[0];

            // Act
            modifiedDetail.Quantity++;

            // Assert
            Assert.Equal(TrackingState.Unchanged, modifiedDetail.TrackingState);
        }

        [Fact]
        public void Existing_Parent_With_Excluded_Children_Should_Not_Add_ModifiedProperty()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var orderDetails = changeTracker[0].OrderDetails;
            orderDetails.ExcludedProperties.Add("Quantity");
            var modifiedDetail = orderDetails[0];

            // Act
            modifiedDetail.Quantity++;

            // Assert
            Assert.True(modifiedDetail.ModifiedProperties == null
                || modifiedDetail.ModifiedProperties.Count == 0);
        }

        [Fact]
        public void Existing_Parent_With_Mixed_Children_Should_Not_Add_ModifiedProperty()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var orderDetails = changeTracker[0].OrderDetails;
            orderDetails.ExcludedProperties.Add("Quantity");
            var modifiedDetail = orderDetails[0];

            // Act
            modifiedDetail.Quantity++;
            modifiedDetail.UnitPrice++;

            // Assert
            Assert.Equal(TrackingState.Modified, modifiedDetail.TrackingState);
            Assert.Contains("UnitPrice", modifiedDetail.ModifiedProperties);
            Assert.DoesNotContain("Quantity", modifiedDetail.ModifiedProperties);
        }

        [Fact]
        public void Existing_Parent_Removed_With_Modified_Children_Should_Have_Children_Modified_Properties_Cleared()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var orderDetails = (IList<OrderDetail>)order.OrderDetails;
            var orderDetail = orderDetails[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            orderDetail.Quantity++;

            // Act
            changeTracker.Remove(order);

            // Assert
            Assert.True(orderDetail.ModifiedProperties == null
                || orderDetail.ModifiedProperties.Count == 0);
        }
        
        #endregion

        #region GetChanges Tests

        [Fact]
        public void GetChanges_On_Unchanged_Order_With_Details_Should_Return_Marked_Children()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var order3 = database.Orders[3];
            var changeTracker = new ChangeTrackingCollection<Order>(order, order3);
            order3.OrderDate += new System.TimeSpan(1, 0, 0, 0); // + one day
            order3.Customer.CustomerName += " (test)";
            var orderDetails = (IList<OrderDetail>)changeTracker[0].OrderDetails;
            var unchangedDetail = orderDetails[0];
            var modifiedDetail = orderDetails[1];
            var deletedDetail = orderDetails[2];
            var addedDetail = new OrderDetail
            {
                ProductId = 1,
                Product = database.Products[0],
                Quantity = 10,
                UnitPrice = 20M
            };
            orderDetails.Add(addedDetail);
            modifiedDetail.UnitPrice++;
            orderDetails.Remove(deletedDetail);

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            var changedOrder = changes.First();
            var changedOrder3 = changes[1];
            var changedModifiedDetail = changedOrder.OrderDetails.Single(d => d.ProductId == modifiedDetail.ProductId);
            var changedAddedDetail = changedOrder.OrderDetails.Single(d => d.ProductId == addedDetail.ProductId);
            var changedDeletedDetail = changedOrder.OrderDetails.Single(d => d.ProductId == deletedDetail.ProductId);
            Assert.Equal(TrackingState.Unchanged, changedOrder.TrackingState);
            Assert.Equal(3, changedOrder.OrderDetails.Count);
            Assert.Equal(TrackingState.Modified, changedModifiedDetail.TrackingState);
            Assert.Equal(TrackingState.Added, changedAddedDetail.TrackingState);
            Assert.Equal(TrackingState.Deleted, changedDeletedDetail.TrackingState);
            Assert.DoesNotContain(unchangedDetail, changedOrder.OrderDetails);
            Assert.NotNull(order.Customer);
            Assert.NotNull(order3.Customer);
            Assert.NotNull(changedOrder.Customer);
            Assert.NotNull(changedOrder3.Customer);
            Assert.True(object.ReferenceEquals(order.Customer, order3.Customer));
            Assert.False(object.ReferenceEquals(order.Customer, changedOrder.Customer));
            Assert.True(object.ReferenceEquals(changedOrder.Customer, changedOrder3.Customer));
        }

        [Fact]
        public void GetChanges_On_Added_Order_With_Details_Should_Return_Marked_Children_Added()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(true) {order};
            var orderDetails = (IList<OrderDetail>)changeTracker[0].OrderDetails;
            var unchangedDetail = orderDetails[0];
            var modifiedDetail = orderDetails[1];
            var deletedDetail = orderDetails[2];
            var addedDetail = new OrderDetail
            {
                ProductId = 1,
                Product = database.Products[0],
                Quantity = 10,
                UnitPrice = 20M
            };
            orderDetails.Add(addedDetail);
            modifiedDetail.UnitPrice++;
            orderDetails.Remove(deletedDetail);

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            var changedOrder = changes.First();
            var changedExistingDetail = changedOrder.OrderDetails.Single(d => d.ProductId == unchangedDetail.ProductId);
            var changedModifiedDetail = changedOrder.OrderDetails.Single(d => d.ProductId == modifiedDetail.ProductId);
            var changedAddedDetail = changedOrder.OrderDetails.Single(d => d.ProductId == addedDetail.ProductId);
            Assert.Equal(TrackingState.Added, changedOrder.TrackingState);
            Assert.Equal(3, changedOrder.OrderDetails.Count);
            Assert.Equal(TrackingState.Added, changedModifiedDetail.TrackingState);
            Assert.Equal(TrackingState.Added, changedAddedDetail.TrackingState);
            Assert.Equal(TrackingState.Added, changedExistingDetail.TrackingState);
            Assert.DoesNotContain(deletedDetail, changedOrder.OrderDetails);
        }

        [Fact]
        public void GetChanges_On_Deleted_Order_With_Details_Should_Return_Marked_Children_Deleted()
        {
            // NOTE: Removed order with added detail should exclude added detail
            // Removed order with deleted detail should include deleted detail

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var orderDetails = (IList<OrderDetail>)changeTracker[0].OrderDetails;
            var unchangedDetail = orderDetails[0];
            var modifiedDetail = orderDetails[1];
            var deletedDetail = orderDetails[2];
            var addedDetail = new OrderDetail
            {
                ProductId = 1,
                Product = database.Products[0],
                Quantity = 10,
                UnitPrice = 20M
            };
            orderDetails.Add(addedDetail);
            modifiedDetail.UnitPrice++;
            orderDetails.Remove(deletedDetail);
            changeTracker.Remove(order);

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            var changedOrder = changes.First();
            var changedExistingDetail = changedOrder.OrderDetails.SingleOrDefault(d => d.ProductId == unchangedDetail.ProductId);
            var changedModifiedDetail = changedOrder.OrderDetails.SingleOrDefault(d => d.ProductId == modifiedDetail.ProductId);
            var changedAddedDetail = changedOrder.OrderDetails.SingleOrDefault(d => d.ProductId == addedDetail.ProductId);
            var changedDeletedDetail = changedOrder.OrderDetails.SingleOrDefault(d => d.ProductId == deletedDetail.ProductId);
            Assert.Equal(TrackingState.Deleted, changedOrder.TrackingState);
            Assert.Equal(3, changedOrder.OrderDetails.Count);
            Assert.Equal(TrackingState.Deleted, changedModifiedDetail.TrackingState);
            Assert.Equal(TrackingState.Deleted, changedExistingDetail.TrackingState);
            Assert.Equal(TrackingState.Deleted, changedDeletedDetail.TrackingState);
            Assert.Null(changedAddedDetail);
            Assert.Equal(TrackingState.Unchanged, addedDetail.TrackingState);
        }

        [Fact]
        public void GetChanges_On_Modified_Order_Should_Return_Order()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.OrderDate = order.OrderDate.AddDays(1);

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.False(changes.Tracking);
            Assert.NotSame(changes[0], order);
            Assert.True(changes[0].IsEquatable(order));
        }

        [Fact]
        public void GetChanges_On_Unchanged_Order_With_Modified_Detail_Should_Return_Order()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.OrderDetails[0].Quantity++;

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.Equal(TrackingState.Unchanged, changes[0].TrackingState);
            Assert.Equal(1, changes[0].OrderDetails.Count);
            Assert.Equal(TrackingState.Modified, changes[0].OrderDetails[0].TrackingState);
            Assert.True(changes[0].IsEquatable(order));
            Assert.True(changes[0].OrderDetails[0].IsEquatable(order.OrderDetails[0]));
        }

        [Fact]
        public void GetChanges_On_Unchanged_OrderDetail_With_Modified_Product_Should_Return_OrderDetail()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.OrderDetails[0].Product.ProductName = "xxx";

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.Equal(TrackingState.Unchanged, changes[0].OrderDetails[0].TrackingState);
            Assert.Equal(1, changes[0].OrderDetails.Count);
            Assert.Equal(TrackingState.Modified, changes[0].OrderDetails[0].Product.TrackingState);
            Assert.True(changes[0].IsEquatable(order));
            Assert.True(changes[0].OrderDetails[0].IsEquatable(order.OrderDetails[0]));
            Assert.True(changes[0].OrderDetails[0].Product.IsEquatable(order.OrderDetails[0].Product));
        }

        [Fact]
        public void GetChanges_With_More_Than_One_ITrackable_Members_Should_Return_NonEmpty_Changeset_if_Modified()
        {
            // Arrange
            var family = new Family
            {
                Father = new Parent
                {
                    Name = "Alan"
                },
                Mother = new Parent
                {
                    Name = "Judith"
                },
                Child = new Child
                {
                    Name = "Jake"
                }
            };

            var changeTracker = new ChangeTrackingCollection<Family>(family);

            // Act
            family.Father.Name = "Herb";
            var changedFamily = changeTracker.GetChanges().SingleOrDefault();

            //Assert
            Assert.NotNull(changedFamily);
            Assert.Equal(TrackingState.Unchanged, changedFamily.TrackingState);
            Assert.NotNull(changedFamily.Father);
            Assert.Equal(TrackingState.Modified, changedFamily.Father.TrackingState);
            Assert.Null(changedFamily.Mother);
            Assert.Null(changedFamily.Child);
        }

        #endregion

        #region MergeChangesTests

        [Fact]
        public void Updated_Parent_With_Children_Should_Merge_Unchanged_Children()
        {
            // Arrange
            var database = new MockNorthwind();

            // Get order, fix up details, clone
            var origOrder = database.Orders[0];
            foreach (var detail in origOrder.OrderDetails)
                detail.Order = origOrder;
            var updatedOrder = origOrder.Clone<Order>();

            // Add unchanged detail to orig order
            origOrder.OrderDetails.Add(new OrderDetail
            {
                ProductId = 1,
                Product = database.Products[0],
                Quantity = 10,
                UnitPrice = 20M,
                OrderId = origOrder.OrderId,
                Order = origOrder
            });

            // Replicate changes in updated order
            updatedOrder.OrderDetails[0].UnitPrice++;
            updatedOrder.OrderDetails.RemoveAt(1);

            // Remove 3rd detail so it can be re-added
            var addedDetail = origOrder.OrderDetails[2];
            origOrder.OrderDetails.Remove(addedDetail);

            // Clone orig order and start tracking
            var changeTracker = new ChangeTrackingCollection<Order>(origOrder);

            // Set state on orig order details
            origOrder.OrderDetails[0].UnitPrice++;
            origOrder.OrderDetails.Add(addedDetail);
            origOrder.OrderDetails.RemoveAt(1);

            // Act

            // Merge updates into orig order
#pragma warning disable 618
            changeTracker.MergeChanges(ref origOrder, updatedOrder);
#pragma warning restore 618

            // Assert
            // Orig reference pointed to updated
            Assert.True(ReferenceEquals(origOrder, updatedOrder));

            // Tracking states set to unchanged
            Assert.Equal(TrackingState.Unchanged, origOrder.OrderDetails[0].TrackingState);
            Assert.Equal(TrackingState.Unchanged, origOrder.OrderDetails[1].TrackingState);
            Assert.Equal(TrackingState.Unchanged, origOrder.OrderDetails[2].TrackingState);

            // Modified properties set to null
            Assert.Null(origOrder.OrderDetails[0].ModifiedProperties);
            Assert.Null(origOrder.OrderDetails[1].ModifiedProperties);
            Assert.Null(origOrder.OrderDetails[2].ModifiedProperties);

            // Detail orders fixed up
            Assert.True(ReferenceEquals(origOrder, origOrder.OrderDetails[0].Order));
            Assert.True(ReferenceEquals(origOrder, origOrder.OrderDetails[1].Order));
            Assert.True(ReferenceEquals(origOrder, origOrder.OrderDetails[2].Order));
        }

        #endregion

        #region ManyToMany - Set Status Tests

        [Fact]
        public void Existing_Employee_With_Territories_Should_Have_Territories_Marked()
        {
            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            var unchangedTerritory = employee.Territories[0];
            var modifiedTerritory = employee.Territories[1];
            var deletedTerritory = employee.Territories[2];
            var addedTerritory = database.Territories[3];

            // Act
            modifiedTerritory.TerritoryDescription = "xxx";
            employee.Territories.Add(addedTerritory);
            employee.Territories.Remove(deletedTerritory);

            // Assert
            Assert.Equal(TrackingState.Unchanged, employee.TrackingState);
            Assert.Equal(TrackingState.Unchanged, unchangedTerritory.TrackingState);
            Assert.Equal(TrackingState.Modified, modifiedTerritory.TrackingState);
            Assert.Equal(TrackingState.Added, addedTerritory.TrackingState);
            Assert.Equal(TrackingState.Deleted, deletedTerritory.TrackingState);
        }

        [Fact]
        public void Added_Employee_With_Territories_Should_Have_Territories_Marked_As_Added()
        {
            // NOTE: Removing child from added parent marks child as unchanged.
            // This is so that GetChanges will not include the removed child.

            // Arrange
            var database = new MockNorthwind();
            var changeTracker = new ChangeTrackingCollection<Employee>(true);
            var employee = database.Employees[0];
            var unchangedTerritory = employee.Territories[0];
            var modifiedTerritory = employee.Territories[1];
            var deletedTerritory = employee.Territories[2];
            var addedTerritory = database.Territories[3];
            changeTracker.Add(employee);

            // Act
            modifiedTerritory.TerritoryDescription = "xxx";
            employee.Territories.Add(addedTerritory);
            employee.Territories.Remove(deletedTerritory);

            // Assert
            Assert.Equal(TrackingState.Added, employee.TrackingState);
            Assert.Equal(TrackingState.Added, unchangedTerritory.TrackingState);
            Assert.Equal(TrackingState.Added, modifiedTerritory.TrackingState);
            Assert.Equal(TrackingState.Added, addedTerritory.TrackingState);
            Assert.Equal(TrackingState.Unchanged, deletedTerritory.TrackingState);
        }

        [Fact]
        public void Added_Employee_Then_Removed_With_Territories_Should_Have_Territories_Marked_As_Unchanged()
        {
            // NOTE: Removing an added parent should mark parent and children as unchanged.
            // This is so that GetChanges will not include parent or children.

            // Arrange
            var database = new MockNorthwind();
            var changeTracker = new ChangeTrackingCollection<Employee>(true);
            var employee = database.Employees[0];
            var unchangedTerritory = employee.Territories[0];
            var modifiedTerritory = employee.Territories[1];
            var deletedTerritory = employee.Territories[2];
            var addedTerritory = database.Territories[3];
            changeTracker.Add(employee);

            // Act
            modifiedTerritory.TerritoryDescription = "xxx";
            employee.Territories.Add(addedTerritory); // stays added
            employee.Territories.Remove(deletedTerritory); // from added to unchanged
            changeTracker.Remove(employee);

            // Assert
            Assert.Equal(TrackingState.Unchanged, employee.TrackingState);
            Assert.Equal(TrackingState.Unchanged, unchangedTerritory.TrackingState);
            Assert.Equal(TrackingState.Unchanged, modifiedTerritory.TrackingState);
            Assert.Equal(TrackingState.Unchanged, addedTerritory.TrackingState);
            Assert.Equal(TrackingState.Unchanged, deletedTerritory.TrackingState);
        }

        [Fact]
        public void Removed_Employee_With_Territories_Should_Have_Territories_Marked_As_Deleted()
        {
            // NOTE: Removing a parent will mark both parent and children as deleted.
            // Deleted M-M childen are simply removed from the relation with parent.
            // 

            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            var unchangedTerritory = employee.Territories[0];
            var modifiedTerritory = employee.Territories[1];
            var deletedTerritory = employee.Territories[2];
            var addedTerritory = database.Territories[3];

            // Act
            modifiedTerritory.TerritoryDescription = "xxx";
            employee.Territories.Add(addedTerritory);
            employee.Territories.Remove(deletedTerritory);
            changeTracker.Remove(employee);

            // Assert
            Assert.Equal(TrackingState.Deleted, employee.TrackingState);
            Assert.Equal(TrackingState.Unchanged, unchangedTerritory.TrackingState);
            Assert.Equal(TrackingState.Modified, modifiedTerritory.TrackingState);
            Assert.Equal(TrackingState.Unchanged, addedTerritory.TrackingState);
            Assert.Equal(TrackingState.Deleted, deletedTerritory.TrackingState);
        }

        #endregion

        #region ManyToMany - Modified Properties Tests

        [Fact]
        public void Existing_Employee_With_Modified_Children_Should_Add_ModifiedProperties()
        {
            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            var modifiedTerritory = employee.Territories[1];

            // Act
            modifiedTerritory.TerritoryDescription = "xxx";

            // Assert
            Assert.Contains("TerritoryDescription", modifiedTerritory.ModifiedProperties);
        }

        [Fact]
        public void Existing_Employee_With_Modified_Children_Should_Add_Multiple_ModifiedProperties()
        {
            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            var modifiedTerritory = employee.Territories[1];

            // Act
            modifiedTerritory.TerritoryDescription = "xxx";
            modifiedTerritory.Data = "xxx";

            // Assert
            Assert.Contains("TerritoryDescription", modifiedTerritory.ModifiedProperties);
            Assert.Contains("Data", modifiedTerritory.ModifiedProperties);
        }

        [Fact]
        public void Existing_Employee_With_Excluded_Children_Should_Not_Be_Marked_As_Modified()
        {
            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            employee.Territories.ExcludedProperties.Add("TerritoryDescription");
            var modifiedTerritory = employee.Territories[1];

            // Act
            modifiedTerritory.TerritoryDescription = "xxx";

            // Assert
            Assert.Equal(TrackingState.Unchanged, modifiedTerritory.TrackingState);
            Assert.True(modifiedTerritory.ModifiedProperties == null
                || modifiedTerritory.ModifiedProperties.Count == 0);
        }

        [Fact]
        public void Existing_Employee_With_Mixed_Children_Should_Not_Add_ModifiedProperties()
        {
            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            employee.Territories.ExcludedProperties.Add("TerritoryDescription");
            var modifiedTerritory = employee.Territories[1];

            // Act
            modifiedTerritory.TerritoryDescription = "xxx";
            modifiedTerritory.Data = "xxx";

            // Assert
            Assert.Equal(TrackingState.Modified, modifiedTerritory.TrackingState);
            Assert.Contains("Data", modifiedTerritory.ModifiedProperties);
            Assert.DoesNotContain("TerritoryDescription", modifiedTerritory.ModifiedProperties);
        }

        [Fact]
        public void Existing_Employee_Removed_With_Modified_Children_Have_Children_ModifiedProperties_Cleared()
        {
            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            var modifiedTerritory = employee.Territories[1];
            modifiedTerritory.TerritoryDescription = "xxx";

            // Act
            changeTracker.Remove(employee);

            // Assert
            Assert.True(modifiedTerritory.ModifiedProperties == null
                || modifiedTerritory.ModifiedProperties.Count == 0);
        }

        #endregion

        #region ManyToMany - GetChanges Tests

        [Fact]
        public void GetChanges_On_Existing_Employee_With_Territories_Should_Return_Marked_Territories()
        {
            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            var unchangedTerritory = employee.Territories[0];
            var modifiedTerritory = employee.Territories[1];
            var deletedTerritory = employee.Territories[2];
            var addedTerritory = database.Territories[3];
            employee.Territories.Add(addedTerritory);
            modifiedTerritory.TerritoryDescription = "xxx";
            employee.Territories.Remove(deletedTerritory);

            // Act
            var changes = changeTracker.GetChanges();
            var changedEmployee = changes.First();
            var changedModifiedTerritory = changedEmployee.Territories.Single(t => t.TerritoryId == modifiedTerritory.TerritoryId);
            var changedAddedTerritory = changedEmployee.Territories.Single(t => t.TerritoryId == addedTerritory.TerritoryId);
            var changedDeletedTerritory = changedEmployee.Territories.Single(t => t.TerritoryId == deletedTerritory.TerritoryId);

            // Assert
            Assert.Equal(TrackingState.Unchanged, changedEmployee.TrackingState);
            Assert.Equal(3, changedEmployee.Territories.Count);
            Assert.Equal(TrackingState.Modified, changedModifiedTerritory.TrackingState);
            Assert.Equal(TrackingState.Added, changedAddedTerritory.TrackingState);
            Assert.Equal(TrackingState.Deleted, changedDeletedTerritory.TrackingState);
            Assert.DoesNotContain(unchangedTerritory, changedEmployee.Territories);
        }

        [Fact]
        public void GetChanges_On_Existing_Employee_With_Territory_And_Modified_Area_Should_Return_Marked_Territory()
        {
            // Ensure that changes are retrieved across M-M relationships.

            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var territory = employee.Territories[0];
            var area = new Area
            {
                AreaId = 1,
                AreaName = "Northern",
                TrackingState = TrackingState.Modified
            };
            territory.AreaId = 1;
            territory.Area = area;
            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            area.AreaName = "xxx"; // Modify area

            // Act
            var changes = changeTracker.GetChanges();
            var changedEmployee = changes.First();
            var changedTerritory = changedEmployee.Territories.Single(t => t.TerritoryId == territory.TerritoryId);
            var changedArea = changedTerritory.Area;

            // Assert
            Assert.Equal(TrackingState.Unchanged, changedEmployee.TrackingState);
            Assert.Equal(TrackingState.Unchanged, changedTerritory.TrackingState);
            Assert.Equal(TrackingState.Modified, changedArea.TrackingState);
            Assert.Contains("AreaName", area.ModifiedProperties);
        }

        [Fact]
        public void GetChanges_On_Modified_Employee_With_Unchanged_Territories_Should_Return_No_Territories()
        {
            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            employee.LastName = "xxx";

            // Act
            var changes = changeTracker.GetChanges();
            var changedEmployee = changes.First();

            // Assert
            Assert.Empty(changedEmployee.Territories);
        }

        #endregion

        #region ManyToOne - Set Status Tests

        [Fact]
        public void Existing_Order_With_Unchanged_Customer_Should_Mark_Customer_As_Unchanged()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);

            // Act

            // Assert
            Assert.Equal(TrackingState.Unchanged, order.TrackingState);
            Assert.Equal(TrackingState.Unchanged, order.Customer.TrackingState);
            Assert.False(order.HasChanges());
        }

        [Fact]
        public void Existing_Order_With_Assigned_Customer_Should_Mark_Customer_As_Modified()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var customer = database.Customers[5];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.Customer = customer;

            // Act
            order.Customer.CustomerName = "xxx";

            // Assert
            Assert.Equal(TrackingState.Unchanged, order.TrackingState);
            Assert.Equal(TrackingState.Modified, order.Customer.TrackingState);
            Assert.True(order.HasChanges());
        }

        [Fact]
        public void Existing_Order_With_Modified_Customer_Should_Mark_Customer_As_Modified()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);

            // Act
            order.Customer.CustomerName = "xxx";

            // Assert
            Assert.Equal(TrackingState.Unchanged, order.TrackingState);
            Assert.Equal(TrackingState.Modified, order.Customer.TrackingState);
            Assert.True(order.HasChanges());
        }

        [Fact]
        public void Existing_Order_With_New_Customer_Should_Mark_Customer_As_Unchanged()
        {
            // NOTE: Setting Order.Customer to a new customer will not automatically
            // mark it as Added, because Order has no way to tell if customer is new
            // or already exists.  However, Customer can be marked as Added manually.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);

            // Act
            // Because not marked as added, refers to existing customer
            order.Customer = new Customer
            {
                CustomerId = "ABCD",
                CustomerName = "Test"
            };

            // NOTE: Reference properties are change-tracked but do not call 
            // NotifyPropertyChanged because it is called by foreign key's property setter.

            // Assert
            Assert.Equal(TrackingState.Unchanged, order.TrackingState);
            Assert.Equal(TrackingState.Unchanged, order.Customer.TrackingState);
            Assert.False(order.HasChanges());
        }

        [Fact]
        public void Existing_Order_With_Manually_Added_Customer_Should_Mark_Customer_As_Added()
        {
            // NOTE: Manually marking reference as added will create a new entity
            // when it is saved.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);

            // Act
            order.Customer = new Customer
            {
                CustomerId = "ABCD",
                CustomerName = "Test",
                TrackingState = TrackingState.Added // required to insert new customer
            };

            // NOTE: Reference properties are change-tracked but do not call 
            // NotifyPropertyChanged because it is called by foreign key's property setter.

            // Assert
            Assert.Equal(TrackingState.Unchanged, order.TrackingState);
            Assert.Equal(TrackingState.Added, order.Customer.TrackingState);
            Assert.True(order.HasChanges());
        }

        [Fact]
        public void Existing_Order_With_Removed_Customer_Should_Mark_Customer_As_Unchanged()
        {
            // NOTE: Setting Order.Customer to null will not automatically
            // mark it as Deleted. Deleting customer from order is not supported
            // because it could be related to other entities. However, it is possible
            // to delete a customer independently.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var customer = order.Customer;

            // Act
            order.Customer = null;

            // NOTE: Reference properties are change-tracked but do not call 
            // NotifyPropertyChanged because it is called by foreign key's property setter.

            // Assert
            Assert.Equal(TrackingState.Unchanged, order.TrackingState);
            Assert.Equal(TrackingState.Unchanged, customer.TrackingState);
            Assert.False(order.HasChanges());
        }

        [Fact]
        public void Added_Order_With_Unchanged_Customer_Should_Mark_Customer_As_Unchanged()
        {
            // NOTE: Referenced customer will remain unchanged because Order has no way to  
            // tell if customer is new or already exists. However, Customer can be marked 
            // as Added manually. (If it were 1-M or M-M, marking parent as added automatically
            // marks children as added.)

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(true);
            changeTracker.Add(order);

            // Act

            // Assert
            Assert.Equal(TrackingState.Added, order.TrackingState);
            Assert.Equal(TrackingState.Unchanged, order.Customer.TrackingState);
            Assert.True(order.HasChanges());
        }

        [Fact]
        public void Added_Order_With_Modified_Customer_Should_Mark_Customer_As_Modified()
        {
            // NOTE: Modified reference entity will remain modified if parent is added.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(true);
            changeTracker.Add(order);

            // Act
            order.Customer.CustomerName = "xxx";

            // Assert
            Assert.Equal(TrackingState.Added, order.TrackingState);
            Assert.Equal(TrackingState.Modified, order.Customer.TrackingState);
            Assert.True(order.HasChanges());
        }

        [Fact]
        public void Added_Order_With_New_Customer_Should_Mark_Customer_As_Unchanged()
        {
            // NOTE: Setting Order.Customer to a new customer will not automatically
            // mark it as Added, because Order has no way to tell if customer is new
            // or already exists.  However, Customer can be marked as Added manually.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(true);
            changeTracker.Add(order);

            // Act
            // Because not marked as added, refers to existing customer
            order.Customer = new Customer
            {
                CustomerId = "ABCD",
                CustomerName = "Test"
            };

            // Assert
            Assert.Equal(TrackingState.Added, order.TrackingState);
            Assert.Equal(TrackingState.Unchanged, order.Customer.TrackingState);
            Assert.True(order.HasChanges());
        }

        [Fact]
        public void Added_Order_With_Manually_Added_Customer_Should_Mark_Customer_As_Added()
        {
            // NOTE: Manually marking reference as added will create a new entity
            // when it is saved.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(true);
            changeTracker.Add(order);

            // Act
            order.Customer = new Customer
            {
                CustomerId = "ABCD",
                CustomerName = "Test",
                TrackingState = TrackingState.Added // required to insert new customer
            };

            // Assert
            Assert.Equal(TrackingState.Added, order.TrackingState);
            Assert.Equal(TrackingState.Added, order.Customer.TrackingState);
            Assert.True(order.HasChanges());
        }

        [Fact]
        public void Added_Order_With_Removed_Customer_Should_Mark_Customer_As_Unchanged()
        {
            // NOTE: Removed customer will not be marked as deleted. Instead to be deleted
            // it must be independently marked as deleted.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(true);
            changeTracker.Add(order);
            var customer = order.Customer;

            // Act
            order.Customer = null;

            // Assert
            Assert.Equal(TrackingState.Added, order.TrackingState);
            Assert.Equal(TrackingState.Unchanged, customer.TrackingState);
            Assert.True(order.HasChanges());
        }

        [Fact]
        public void Removed_Order_With_Unchanged_Customer_Should_Mark_Customer_As_Unchanged()
        {
            // NOTE: Removing order will not automatically mark customer as deleted.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var customer = order.Customer;

            // Act
            changeTracker.Remove(order);

            // Assert
            Assert.Equal(TrackingState.Deleted, order.TrackingState);
            Assert.Equal(TrackingState.Unchanged, order.Customer.TrackingState);
            Assert.True(order.HasChanges());
        }

        [Fact]
        public void Removed_Order_With_Modified_Customer_Should_Mark_Customer_As_Modified()
        {
            // NOTE: Modified reference entity will remain modified if parent is deleted.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.Customer.CustomerName = "xxx";

            // Act
            changeTracker.Remove(order);

            // Assert
            Assert.Equal(TrackingState.Deleted, order.TrackingState);
            Assert.Equal(TrackingState.Modified, order.Customer.TrackingState);
            Assert.True(order.HasChanges());
        }

        [Fact]
        public void Removed_Order_With_New_Customer_Should_Mark_Customer_As_Unchanged()
        {
            // NOTE: Setting Order.Customer to null will not mark customer as deleted.
            // Because customer not marked as deleted, it refers to an existing customer.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.Customer = new Customer
            {
                CustomerId = "ABCD",
                CustomerName = "Test"
            };

            // Act
            changeTracker.Remove(order);

            // Assert
            Assert.Equal(TrackingState.Deleted, order.TrackingState);
            Assert.Equal(TrackingState.Unchanged, order.Customer.TrackingState);
            Assert.True(order.HasChanges());
        }

        [Fact]
        public void Removed_Order_With_Manually_Added_Customer_Should_Mark_Customer_As_Added()
        {
            // NOTE: Manually marking reference as added will create a new entity
            // when it is saved.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.Customer = new Customer
            {
                CustomerId = "ABCD",
                CustomerName = "Test",
                TrackingState = TrackingState.Added
            };

            // Act
            changeTracker.Remove(order);

            // Assert
            Assert.Equal(TrackingState.Deleted, order.TrackingState);
            Assert.Equal(TrackingState.Added, order.Customer.TrackingState);
            Assert.True(order.HasChanges());
        }

        [Fact]
        public void Removed_Order_With_Removed_Customer_Should_Mark_Customer_As_Unchanged()
        {
            // NOTE: Removed customer will not be marked as deleted. Instead to be deleted
            // it must be independently marked as deleted.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var customer = order.Customer;
            order.Customer = null;

            // Act
            changeTracker.Remove(order);

            // Assert
            Assert.Equal(TrackingState.Deleted, order.TrackingState);
            Assert.Equal(TrackingState.Unchanged, customer.TrackingState);
            Assert.True(order.HasChanges());
        }

        #endregion

        #region ManyToOne - Modified Properties Tests

        [Fact]
        public void Existing_Order_With_Modified_Customer_Should_Add_ModifiedProperties()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);

            // Act
            order.Customer.CustomerName = "xxx";

            // Assert
            Assert.Contains("CustomerName", order.Customer.ModifiedProperties);
        }

        [Fact]
        public void Existing_Order_With_Modified_Customer_Should_Add_Multiple_ModifiedProperties()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);

            // Act
            order.Customer.CustomerName = "xxx";
            order.Customer.Data = "xxx";

            // Assert
            Assert.Contains("CustomerName", order.Customer.ModifiedProperties);
            Assert.Contains("Data", order.Customer.ModifiedProperties);
        }

        [Fact]
        public void Existing_Order_Removed_With_Modified_Customer_Has_Children_ModifiedProperties_Cleared()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var modifiedCustomer = order.Customer;
            modifiedCustomer.CustomerName = "xxx";
            order.OrderDetails[0].ModifiedProperties = new List<string> { "UnitPrice "};

            // Act
            changeTracker.Remove(order);

            // Assert
            Assert.True(modifiedCustomer.ModifiedProperties.Count == 1);
            Assert.True(order.OrderDetails[0].ModifiedProperties == null);
        }

        #endregion

        #region ManyToOne - GetChanges Tests

        [Fact]
        public void GetChanges_On_Existing_Order_With_Unchanged_Customer_Should_Return_Empty_Collection()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.Empty(changes);
        }

        [Fact]
        public void GetChanges_On_Existing_Order_With_Modified_Customer_Should_Return_Customer_Marked_As_Modified()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.Customer.CustomerName = "xxx";

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.NotEmpty(changes);
            Assert.Equal(TrackingState.Unchanged, changes.First().TrackingState);
            Assert.Equal(TrackingState.Modified, changes.First().Customer.TrackingState);
        }

        [Fact]
        public void GetChanges_On_Existing_Order_With_New_Customer_Should_Return_Empty_Collection()
        {
            // NOTE: Reference properties not explicitly marked as Added will be considered
            // unchanged.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.Customer = new Customer()
            {
                CustomerId = "ABCD",
                CustomerName = "Test"
            };

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.Empty(changes);
        }

        [Fact]
        public void GetChanges_On_Existing_Order_With_Manually_Added_Customer_Should_Return_Customer_Marked_As_Added()
        {
            // NOTE: Reference properties must be explicitly marked as Added.
            
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.Customer = new Customer()
            {
                CustomerId = "ABCD",
                CustomerName = "Test",
                TrackingState = TrackingState.Added
            };

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.NotEmpty(changes);
            Assert.Equal(TrackingState.Unchanged, changes.First().TrackingState);
            Assert.Equal(TrackingState.Added, changes.First().Customer.TrackingState);
        }

        [Fact]
        public void GetChanges_On_Existing_Order_With_Removed_Customer_Should_Return_Empty_Collection()
        {
            // NOTE: Reference properties are change-tracked but do not call 
            // NotifyPropertyChanged because it is called by foreign key's property setter.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var customer = order.Customer;
            order.Customer = null;

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.Empty(changes);
            Assert.Equal(TrackingState.Unchanged, customer.TrackingState);
        }

        [Fact]
        public void GetChanges_On_Existing_Order_With_Customer_Modified_Territory_Should_Return_Territory_Marked_As_Modified()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            order.Customer.Territory = new Territory
            {
                TerritoryId = "91360", TerritoryDescription = "Southern California",
                Customers = new ChangeTrackingCollection<Customer> { order.Customer }
            };
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.Customer.Territory.TerritoryDescription = "xxx";

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.NotEmpty(changes);
            Assert.Equal(TrackingState.Unchanged, changes.First().TrackingState);
            Assert.Equal(TrackingState.Unchanged, changes.First().Customer.TrackingState);
            Assert.Equal(TrackingState.Modified, changes.First().Customer.Territory.TrackingState);
        }

        [Fact]
        public void GetChanges_On_Modified_Order_With_UnModified_Customer_Should_Set_Customer_To_Null()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            order.Customer.Territory = new Territory
            {
                TerritoryId = "91360",
                TerritoryDescription = "Southern California",
                Customers = new ChangeTrackingCollection<Customer> { order.Customer }
            };
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.OrderDate = order.OrderDate.AddDays(1);

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.NotEmpty(changes);
            Assert.Equal(TrackingState.Modified, changes.First().TrackingState);
            Assert.Null(changes.First().Customer);
        }

        [Fact]
        public void GetChanges_On_Existing_Order_With_Modified_Customer_With_Unmodified_Territory_Should_Set_Territory_To_Null()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            order.Customer.Territory = new Territory
            {
                TerritoryId = "91360",
                TerritoryDescription = "Southern California",
                Customers = new ChangeTrackingCollection<Customer> { order.Customer }
            };
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.Customer.CustomerName = "xxx";

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.NotEmpty(changes);
            Assert.Equal(TrackingState.Unchanged, changes.First().TrackingState);
            Assert.Equal(TrackingState.Modified, changes.First().Customer.TrackingState);
            Assert.Null(changes.First().Customer.Territory);
        }

        [Fact]
        public void GetChanges_On_Existing_Order_With_Modified_Customer_With_Deleted_Territory_Should_Return_Marked_Territory()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            order.Customer.Territory = new Territory
            {
                TerritoryId = "91360",
                TerritoryDescription = "Southern California",
                Customers = new ChangeTrackingCollection<Customer> { order.Customer }
            };
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.Customer.CustomerName = "xxx";
            order.Customer.Territory.TrackingState = TrackingState.Deleted;

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.NotEmpty(changes);
            Assert.Equal(TrackingState.Unchanged, changes.First().TrackingState);
            Assert.Equal(TrackingState.Modified, changes.First().Customer.TrackingState);
            Assert.Equal(TrackingState.Deleted, changes.First().Customer.Territory.TrackingState);
        }

        [Fact]
        public void GetChanges_On_Existing_Order_With_Customer_Territory_Added_Modified_Removed_Employees_Should_Return_Marked_Employees()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            order.Customer.Territory = new Territory
            {
                TerritoryId = "91360",
                TerritoryDescription = "Southern California",
                Customers = new ChangeTrackingCollection<Customer> { order.Customer }
            };
            var employee1 = database.Employees[0];
            var employee2 = database.Employees[1];
            var employee3 = database.Employees[2];
            var employee4 = database.Employees[3];
            employee1.Territories.Add(order.Customer.Territory);
            employee2.Territories.Add(order.Customer.Territory);
            employee3.Territories.Add(order.Customer.Territory);
            employee4.Territories.Add(order.Customer.Territory);
            order.Customer.Territory.Employees = new ChangeTrackingCollection<Employee>
                { employee1, employee2, employee3 };
            var changeTracker = new ChangeTrackingCollection<Order>(order);

            employee2.FirstName = "xxx";
            order.Customer.Territory.Employees.Remove(employee3);
            order.Customer.Territory.Employees.Add(employee4);

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.NotEmpty(changes);
            var changedOrder = changes.First();
            Assert.Equal(TrackingState.Unchanged, changedOrder.TrackingState);
            Assert.Equal(TrackingState.Unchanged, changedOrder.Customer.TrackingState);
            Assert.Equal(TrackingState.Unchanged, changedOrder.Customer.Territory.TrackingState);
            Assert.Equal(3, changedOrder.Customer.Territory.Employees.Count);
            Assert.Equal(TrackingState.Modified, changedOrder.Customer.Territory.Employees[0].TrackingState);
            Assert.Equal(TrackingState.Added, changedOrder.Customer.Territory.Employees[1].TrackingState);
            Assert.Equal(TrackingState.Deleted, changedOrder.Customer.Territory.Employees[2].TrackingState);
        }

        #endregion

        #region OneToOne - Set Status Tests

        [Fact]
        public void Existing_Customer_With_Unchanged_CustomerSetting_Should_Have_CustomerSetting_Marked_As_Unchanged()
        {
            // Arrange
            var database = new MockNorthwind();
            var customer = database.Customers[0];
            var customerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Setting = "Setting1",
                Customer = customer
            };
            customer.CustomerSetting = customerSetting;
            var changeTracker = new ChangeTrackingCollection<Customer>(customer);

            // Act

            // Assert
            Assert.Equal(TrackingState.Unchanged, customer.TrackingState);
            Assert.Equal(TrackingState.Unchanged, customerSetting.TrackingState);
        }

        [Fact]
        public void Existing_Customer_With_Modified_CustomerSetting_Should_Have_CustomerSetting_Marked_As_Modified()
        {
            // Arrange
            var database = new MockNorthwind();
            var customer = database.Customers[0];
            var customerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Setting = "Setting1",
                Customer = customer
            };
            customer.CustomerSetting = customerSetting;
            var changeTracker = new ChangeTrackingCollection<Customer>(customer);

            // Act
            customer.CustomerSetting.Setting = "xxx";

            // Assert
            Assert.Equal(TrackingState.Unchanged, customer.TrackingState);
            Assert.Equal(TrackingState.Modified, customerSetting.TrackingState);
        }

        [Fact]
        public void Existing_Customer_With_Assigned_CustomerSetting_Should_Have_CustomerSetting_Marked_As_Modified()
        {
            // Arrange
            var database = new MockNorthwind();
            var customer = database.Customers[0];
            var customerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Setting = "Setting1",
                Customer = customer
            };
            var changeTracker = new ChangeTrackingCollection<Customer>(customer);
            customer.CustomerSetting = customerSetting; // will be tracked

            // Act
            customer.CustomerSetting.Setting = "xxx";

            // Assert
            Assert.Equal(TrackingState.Unchanged, customer.TrackingState);
            Assert.Equal(TrackingState.Modified, customerSetting.TrackingState);
        }

        [Fact]
        public void Existing_Customer_With_New_CustomerSetting_Should_Have_CustomerSetting_Marked_As_Unchanged()
        {
            // Arrange
            var database = new MockNorthwind();
            var customer = database.Customers[0];
            var changeTracker = new ChangeTrackingCollection<Customer>(customer);

            // Act
            var customerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Setting = "Setting1",
                Customer = customer
            };
            customer.CustomerSetting = customerSetting;

            // Assert
            Assert.Equal(TrackingState.Unchanged, customer.TrackingState);
            Assert.Equal(TrackingState.Unchanged, customerSetting.TrackingState);
        }

        [Fact]
        public void Existing_Customer_With_Manually_Added_CustomerSetting_Should_Have_CustomerSetting_Marked_As_Added()
        {
            // Arrange
            var database = new MockNorthwind();
            var customer = database.Customers[0];
            var changeTracker = new ChangeTrackingCollection<Customer>(customer);

            // Act
            var customerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Setting = "Setting1",
                Customer = customer,
                TrackingState = TrackingState.Added
            };
            customer.CustomerSetting = customerSetting;

            // Assert
            Assert.Equal(TrackingState.Unchanged, customer.TrackingState);
            Assert.Equal(TrackingState.Added, customerSetting.TrackingState);
        }

        [Fact]
        public void Existing_Customer_With_Removed_CustomerSetting_Should_Have_CustomerSetting_Marked_As_Unchanged()
        {
            // Arrange
            var database = new MockNorthwind();
            var customer = database.Customers[0];
            var customerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Setting = "Setting1",
                Customer = customer
            };
            customer.CustomerSetting = customerSetting;
            var changeTracker = new ChangeTrackingCollection<Customer>(customer);

            // Act
            customer.CustomerSetting = null;

            // Assert
            Assert.Equal(TrackingState.Unchanged, customer.TrackingState);
            Assert.Equal(TrackingState.Unchanged, customerSetting.TrackingState);
        }

        #endregion

        #region OneToOne - Modified Properties Tests

        [Fact]
        public void Existing_Customer_With_Modified_CustomerSetting_Should_Add_ModifiedProperties()
        {
            // Arrange
            var database = new MockNorthwind();
            var customer = database.Customers[0];
            customer.CustomerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Setting = "Setting1",
                Customer = customer
            };
            var changeTracker = new ChangeTrackingCollection<Customer>(customer);

            // Act
            customer.CustomerSetting.Setting = "xxx";

            // Assert
            Assert.Contains("Setting", customer.CustomerSetting.ModifiedProperties);
        }

        #endregion

        #region OneToOne - GetChangesTests

        [Fact]
        public void GetChanges_On_Existing_Customer_With_Unchanged_CustomerSetting_Should_Return_Empty_Collection()
        {
            // Arrange
            var database = new MockNorthwind();
            var customer = database.Customers[0];
            customer.CustomerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Setting = "Setting1",
                Customer = customer
            };
            var changeTracker = new ChangeTrackingCollection<Customer>(customer);

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.Empty(changes);
        }

        [Fact]
        public void GetChanges_On_Existing_Customer_With_Modified_CustomerSetting_Return_CustomerSetting_Marked_As_Modified()
        {
            // Arrange
            var database = new MockNorthwind();
            var customer = database.Customers[0];
            customer.CustomerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Setting = "Setting1",
                Customer = customer
            };
            var changeTracker = new ChangeTrackingCollection<Customer>(customer);

            // Act
            customer.CustomerSetting.Setting = "xxx";
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.NotEmpty(changes);
            Assert.Equal(TrackingState.Unchanged, changes.First().TrackingState);
            Assert.Equal(TrackingState.Modified, changes.First().CustomerSetting.TrackingState);
        }

        [Fact]
        public void GetChanges_On_Existing_Customer_With_New_CustomerSetting_Return_Empty_Collection()
        {
            // Arrange
            var database = new MockNorthwind();
            var customer = database.Customers[0];
            var changeTracker = new ChangeTrackingCollection<Customer>(customer);
            customer.CustomerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Setting = "Setting1",
                Customer = customer
            };

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.Empty(changes);
        }

        [Fact]
        public void GetChanges_On_Existing_Customer_With_Manually_Added_CustomerSetting_Return_CustomerSetting_Marked_As_Added()
        {
            // Arrange
            var database = new MockNorthwind();
            var customer = database.Customers[0];
            var changeTracker = new ChangeTrackingCollection<Customer>(customer);
            customer.CustomerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Setting = "Setting1",
                Customer = customer,
                TrackingState = TrackingState.Added
            };

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.NotEmpty(changes);
            Assert.Equal(TrackingState.Unchanged, changes.First().TrackingState);
            Assert.Equal(TrackingState.Added, changes.First().CustomerSetting.TrackingState);
        }

        [Fact]
        public void GetChanges_On_Existing_Customer_With_Removed_CustomerSetting_Return_Empty_Collection()
        {
            // Arrange
            var database = new MockNorthwind();
            var customer = database.Customers[0];
            customer.CustomerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Setting = "Setting1",
                Customer = customer
            };
            var customerSetting = customer.CustomerSetting;
            var changeTracker = new ChangeTrackingCollection<Customer>(customer);
            customer.CustomerSetting = null;

            // Act
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.Empty(changes);
            Assert.Equal(TrackingState.Unchanged, customerSetting.TrackingState);
        }

        [Fact]
        public void GetChanges_On_Deleted_Customer_With_Deleted_CustomerSetting_Should_Return_CustomerSetting_Marked_As_Deleted()
        {
            // Arrange
            var database = new MockNorthwind();
            var customer = database.Customers[0];
            customer.CustomerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Setting = "Setting1",
                Customer = customer
            };
            var changeTracker = new ChangeTrackingCollection<Customer>(customer);

            // Act
            customer.CustomerSetting.TrackingState = TrackingState.Deleted;
            changeTracker.Remove(customer);
            var changes = changeTracker.GetChanges();

            // Assert
            Assert.NotEmpty(changes);
            Assert.Equal(TrackingState.Deleted, changes.First().TrackingState);
            Assert.Equal(TrackingState.Deleted, changes.First().CustomerSetting.TrackingState);
        }

        #endregion
    }
}


<|start_filename|>Extensions/Common/Wizards/EntitiesSelectionWizard/Constants.cs<|end_filename|>
﻿using System;

namespace EntitiesSelectionWizard
{
    internal static class Constants
    {
        public static class Descriptions
        {
            public const string ClientEntities = "Client Entities:\r\n" +
            "Adds a class library project with code generation templates for reverse engineering trackable client entities from a database.";

            public const string ServiceEntities = "Service Entities:\r\n" +
            "Adds a class library project with code generation templates for reverse engineering trackable service entities from a database.";

            public const string ClientServiceEntities = "Separate Client / Service Entities:\r\n" +
            "Adds a class library project with code generation templates for reverse engineering trackable client entities from a database.";

            public const string SharedEntities = "Shared Entities:\r\n" +
                "Adds a class library project with code generation templates for reverse engineering trackable shared entities from a database.";

            public const string PortableEntities = "{0} Portable Entities:\r\n" +
                "Adds a portable class library project that is compatible with .Net 4.5 or greater, Windows Store 8, Windows Phone 8 or 8.1, iOS and Android.";

            public const string DotNetEntities = "{0} .Net 4.5 Entities:\r\n" +
                "Adds a .Net 4.5 class library project that is compatible with .Net 4.5 or greater.";
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.ModelFirst/WebApiSample.Service.Entities/Customer.cs<|end_filename|>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace WebApiSample.Service.Entities
{
    using System;
    using System.Collections.Generic;
    using TrackableEntities;
    
    public partial class Customer : ITrackable, IMergeable
    {
        public Customer()
        {
            this.Orders = new List<Order>();
            this.Location = new Location();
        }
    
        public string CustomerId { get; set; }
        public string CompanyName { get; set; }
        public string ContactName { get; set; }
    
        public Location Location { get; set; }
    
        public CustomerSetting CustomerSetting { get; set; }
        public ICollection<Order> Orders { get; set; }
    
        public TrackingState TrackingState { get; set; }
        public ICollection<string> ModifiedProperties { get; set; }
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm.WpfClient/Services/OrderServiceAgent.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using WebApiSample.Mvvm.Client.Entities.Models;

namespace WebApiSample.Mvvm.WpfClient
{
    public class OrderServiceAgent : IOrderServiceAgent
    {
        public async Task<IEnumerable<Order>> GetCustomerOrders(string customerId)
        {
            string request = "api/Order?customerId=" + customerId;
            var response = await ServiceProxy.Instance.GetAsync(request);
            response.EnsureSuccessStatusCode();
            var result = await response.Content.ReadAsAsync<IEnumerable<Order>>(new[] { ServiceProxy.Formatter });
            return result;
        }

        public async Task<Order> GetOrder(int orderId)
        {
            string request = "api/Order/" + orderId;
            var response = await ServiceProxy.Instance.GetAsync(request);
            response.EnsureSuccessStatusCode();
            var result = await response.Content.ReadAsAsync<Order>(new[] { ServiceProxy.Formatter });
            return result;
        }

        public async Task<Order> CreateOrder(Order order)
        {
            string request = "api/Order";
            var response = await ServiceProxy.Instance.PostAsync(request, order, ServiceProxy.Formatter);
            response.EnsureSuccessStatusCode();
            var result = await response.Content.ReadAsAsync<Order>(new[] { ServiceProxy.Formatter });
            return result;
        }

        public async Task<Order> UpdateOrder(Order order)
        {
            string request = "api/Order";
            var response = await ServiceProxy.Instance.PutAsync(request, order, ServiceProxy.Formatter);
            response.EnsureSuccessStatusCode();
            var result = await response.Content.ReadAsAsync<Order>(new[] { ServiceProxy.Formatter });
            return result;
        }

        public async Task DeleteOrder(int orderId)
        {
            string request = "api/Order/" + orderId;
            var response =  await ServiceProxy.Instance.DeleteAsync(request);
            response.EnsureSuccessStatusCode();
        }

        public async Task<bool> VerifyOrderDeleted(int orderId)
        {
            string request = "api/Order/" + orderId;
            var response = await ServiceProxy.Instance.GetAsync(request);
            if (response.IsSuccessStatusCode) return false;
            return true;
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample/WebApiSample.WebApi/Areas/HelpPage/Views/Help/DisplayTemplates/SimpleTypeModelDescription.cshtml<|end_filename|>
@using WebApiSample.Service.WebApi.Areas.HelpPage.ModelDescriptions
@model SimpleTypeModelDescription
@Model.Documentation

<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm.WpfClient/Views/OrderDetailView.xaml.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using SimpleMvvmToolkit;
using WebApiSample.Mvvm.Client.Entities.Models;

namespace WebApiSample.Mvvm.WpfClient
{
    /// <summary>
    /// Interaction logic for OrderDetailView.xaml
    /// </summary>
    public partial class OrderDetailView : Window
    {
        public OrderDetailView(Order order)
        {
            InitializeComponent();

            // Initialize view model
            ViewModel = (OrderViewModelDetail)DataContext;
            ViewModel.Initialize(order);
            ViewModel.ErrorNotice += OnErrorNotice;
            ViewModel.ResultNotice += OnResultNotice;
        }

        public OrderViewModelDetail ViewModel { get; private set; }

        private void OnResultNotice(object sender, NotificationEventArgs<bool> eventArgs)
        {
            DialogResult = eventArgs.Data;
        }

        private void OnErrorNotice(object sender, NotificationEventArgs<Exception> eventArgs)
        {
            MessageBox.Show(eventArgs.Data.Message, "Error");
        }

        private void OnUnloaded(object sender, RoutedEventArgs e)
        {
            ViewModel.ErrorNotice -= OnErrorNotice;
            ViewModel.ResultNotice -= OnResultNotice;
        }
    }
}


<|start_filename|>Samples/VS2012/WcfSample/WcfSample.Service.Entities/Models/Mapping/OrderMap.cs<|end_filename|>
using System.Data.Entity.ModelConfiguration;

namespace WcfSample.Service.Entities.Models.Mapping
{
    public class OrderMap : EntityTypeConfiguration<Order>
    {
        public OrderMap()
        {
            // Primary Key
            this.HasKey(t => t.OrderId);

            // Properties
            this.Property(t => t.CustomerId)
                .IsFixedLength()
                .HasMaxLength(5);

            // Table & Column Mappings
            this.ToTable("Order");
            this.Property(t => t.OrderId).HasColumnName("OrderId");
            this.Property(t => t.CustomerId).HasColumnName("CustomerId");
            this.Property(t => t.OrderDate).HasColumnName("OrderDate");
            this.Property(t => t.ShippedDate).HasColumnName("ShippedDate");
            this.Property(t => t.ShipVia).HasColumnName("ShipVia");
            this.Property(t => t.Freight).HasColumnName("Freight");

            // Tracking Properties
			this.Ignore(t => t.TrackingState);
			this.Ignore(t => t.ModifiedProperties);

            // Relationships
            this.HasOptional(t => t.Customer)
                .WithMany(t => t.Orders)
                .HasForeignKey(d => d.CustomerId);

        }
    }
}


<|start_filename|>Source/TrackableEntities.Common/ObjectReferenceEqualityComparer.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace TrackableEntities.Common
{
    /// <summary>
    /// Compares objects using reference equality.
    /// </summary>
    /// <typeparam name="T">Type of the object</typeparam>
    public sealed class ObjectReferenceEqualityComparer<T> : IEqualityComparer<T>
        where T : class
    {
        private ObjectReferenceEqualityComparer()
        {
        }

        static ObjectReferenceEqualityComparer()
        {
            Default = new ObjectReferenceEqualityComparer<T>();
        }

        /// <summary>
        /// Single instance of the comparer.
        /// </summary>
        public static ObjectReferenceEqualityComparer<T> Default { get; private set; }

        /// <summary>
        /// Determines whether the specified objects are equal.
        /// </summary>
        /// <param name="x">The first object of type T to compare.</param>
        /// <param name="y">The second object of type T to compare.</param>
        /// <returns>true if the specified objects are equal; otherwise, false.</returns>
        public bool Equals(T x, T y)
        {
            return object.ReferenceEquals(x, y);
        }

        /// <summary>
        /// Returns a hash code for the specified object.
        /// </summary>
        /// <param name="obj">The System.Object for which a hash code is to be returned.</param>
        /// <returns>A hash code for the specified object.</returns>
        public int GetHashCode(T obj)
        {
            return RuntimeHelpers.GetHashCode(obj);
        }
    }
}


<|start_filename|>Extensions/Common/Wizards/ItemTemplateParametersWizard/ModelTypeInfo.cs<|end_filename|>
﻿using System;

namespace ItemTemplateParametersWizard
{
    [Serializable]
    public class ModelTypeInfo
    {
        public string DisplayName { get; set; }
        public string Namespace { get; set; }
        public string Name { get; set; }
        public ModelType ModelType { get; set; }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm/WebApiSample.Mvvm.Service.Entities/Models/Territory.cs<|end_filename|>
using System;
using System.Collections.Generic;
using TrackableEntities;

namespace WebApiSample.Mvvm.Service.Entities.Models
{
    public partial class Territory : ITrackable, IMergeable
    {
        public Territory()
        {
            this.Employees = new List<Employee>();
        }

        public string TerritoryId { get; set; }
        public string TerritoryDescription { get; set; }
        public List<Employee> Employees { get; set; }

        public TrackingState TrackingState { get; set; }
        public ICollection<string> ModifiedProperties { get; set; }
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Extensions/VS2012/Deploy/TrackableEntities.TemplateWizard/Constants.cs<|end_filename|>
﻿using System;

namespace TrackableEntities.TemplateWizard
{
    internal static class Constants
    {
        public static class ProjectTemplates
        {
            public const string TrackableWebApi = "TrackableWebApi";
            public const string TrackableWcfService = "TrackableWcfService";
        }

        public static class ReadMeFiles
        {
            public const string TrackableWcf= "TrackableWcf.ReadMe.txt";
            public const string TrackableWebApi = "TrackableWebApi.ReadMe.txt";
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample/WebApiSample.Shared.Entities.Portable/Models/Territory.cs<|end_filename|>
using System;
using System.Collections.Generic;
using TrackableEntities.Client;

namespace WebApiSample.Shared.Entities.Portable.Models
{
    public partial class Territory : EntityBase
    {
		public Territory()
		{
			this.Employees = new ChangeTrackingCollection<Employee>();
		}

		public string TerritoryId
		{ 
			get { return _TerritoryId; }
			set
			{
				if (Equals(value, _TerritoryId)) return;
				_TerritoryId = value;
				NotifyPropertyChanged(() => TerritoryId);
			}
		}
		private string _TerritoryId;

		public string TerritoryDescription
		{ 
			get { return _TerritoryDescription; }
			set
			{
				if (Equals(value, _TerritoryDescription)) return;
				_TerritoryDescription = value;
				NotifyPropertyChanged(() => TerritoryDescription);
			}
		}
		private string _TerritoryDescription;

		public ChangeTrackingCollection<Employee> Employees
		{
			get { return _Employees; }
			set
			{
				if (value != null) value.Parent = this;
				if (Equals(value, _Employees)) return;
				_Employees = value;
				NotifyPropertyChanged(() => Employees);
			}
		}
		private ChangeTrackingCollection<Employee> _Employees;

	}
}


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm.WpfClient/ViewModels/CustomerOrdersViewModel.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using SimpleMvvmToolkit;
using TrackableEntities.Client;
using WebApiSample.Mvvm.Client.Entities.Models;

namespace WebApiSample.Mvvm.WpfClient
{
    /// <summary>
    /// This class contains properties that a View can data bind to.
    /// <para>
    /// Use the <strong>mvvmprop</strong> snippet to add bindable properties to this ViewModel.
    /// </para>
    /// </summary>
    public class CustomerOrdersViewModel : ViewModelBase<CustomerOrdersViewModel>
    {
        private readonly ICustomerServiceAgent _customerServiceAgent;
        private readonly IOrderServiceAgent _orderServiceAgent;

        public event EventHandler<NotificationEventArgs<Exception>> ErrorNotice;
        public event EventHandler<NotificationEventArgs<Order>> CreateOrderNotice;
        public event EventHandler<NotificationEventArgs<Order>> ModifyOrderNotice;
        public event EventHandler<NotificationEventArgs<Order, bool>> DeleteOrderNotice;
        public event EventHandler<NotificationEventArgs> DeleteVerifiedNotice;

        public CustomerOrdersViewModel(
            ICustomerServiceAgent customerServiceAgent,
            IOrderServiceAgent orderServiceAgent)
        {   
            SelectedCustomerIndex = -1;
            _customerServiceAgent = customerServiceAgent;
            _orderServiceAgent = orderServiceAgent;
        }

        private Customer _selectedCustomer;
        public Customer SelectedCustomer
        {
            get { return _selectedCustomer; }
            set
            {
                _selectedCustomer = value;
                NotifyPropertyChanged(m => m.SelectedCustomer);
            }
        }

        private Order _selectedOrder;
        public Order SelectedOrder
        {
            get { return _selectedOrder; }
            set
            {
                _selectedOrder = value;
                NotifyPropertyChanged(m => m.SelectedOrder);
            }
        }

        private List<Customer> _customers;
        public List<Customer> Customers
        {
            get { return _customers; }
            set
            {
                _customers = value;
                NotifyPropertyChanged(m => m.Customers);
            }
        }

        private int _selectedCustomerIndex;
        public int SelectedCustomerIndex
        {
            get { return _selectedCustomerIndex; }
            set
            {
                _selectedCustomerIndex = value;
                NotifyPropertyChanged(m => m.SelectedCustomerIndex);
            }
        }

        private int _selectedOrderIndex;
        public int SelectedOrderIndex
        {
            get { return _selectedOrderIndex; }
            set
            {
                _selectedOrderIndex = value;
                NotifyPropertyChanged(m => m.SelectedOrderIndex);
            }
        }

        private ChangeTrackingCollection<Order> _customerOrders;
        public ChangeTrackingCollection<Order> CustomerOrders
        {
            get { return _customerOrders; }
            set
            {
                _customerOrders = value;
                NotifyPropertyChanged(m => m.CustomerOrders);
            }
        }

        public async void LoadCustomers()
        {
            try
            {
                var customers = await _customerServiceAgent.GetCustomers();
                Customers = new List<Customer>(customers);
                if (Customers.Count > 0)
                    SelectedCustomerIndex = 0;
            }
            catch (Exception ex)
            {
                NotifyError(null, ex);
            }
        }

        public async void LoadCustomerOrders()
        {
            if (SelectedCustomer == null) return;
            try
            {
                var orders = await _orderServiceAgent.GetCustomerOrders(SelectedCustomer.CustomerId);
                CustomerOrders = new ChangeTrackingCollection<Order>(orders);
                if (CustomerOrders.Count > 0)
                    SelectedOrderIndex = 0;
            }
            catch (Exception ex)
            {
                NotifyError(null, ex);
            }
        }

        public void CreateNewOrder()
        {
            if (SelectedCustomer == null) return;
            var order = new Order
            {
                Customer = SelectedCustomer,
                CustomerId = SelectedCustomer.CustomerId
            };
            Notify(CreateOrderNotice, new NotificationEventArgs<Order>(null, order));
        }

        public void ModifyOrder()
        {
            if (SelectedOrder == null) return;
            Notify(ModifyOrderNotice, new NotificationEventArgs<Order>(null, SelectedOrder));
        }

        public void DeleteOrder()
        {
            if (SelectedOrder == null) return;
            Notify(DeleteOrderNotice, new NotificationEventArgs<Order, bool>(null,
                SelectedOrder, OnDeleteNoticeCompleted));
        }

        private async void OnDeleteNoticeCompleted(bool confirmed)
        {
            if (confirmed)
            {
                try
                {
                    // Delete order
                    await _orderServiceAgent.DeleteOrder(SelectedOrder.OrderId);

                    // Verify order deletion
                    bool deleted = await _orderServiceAgent.VerifyOrderDeleted(SelectedOrder.OrderId);
                    if (deleted)
                    {
                        CustomerOrders.Remove(SelectedOrder);
                        Notify(DeleteVerifiedNotice, new NotificationEventArgs());
                    }
                }
                catch (Exception ex)
                {
                    NotifyError(null, ex);
                }
            }
        }

        public void AddNewOrder(Order order)
        {
            if (order == null) return;
            CustomerOrders.Tracking = false;
            CustomerOrders.Add(order);
            CustomerOrders.Tracking = true;
            SelectedOrderIndex = CustomerOrders.Count - 1;
        }

        private void NotifyError(string message, Exception error)
        {
            Notify(ErrorNotice, new NotificationEventArgs<Exception>(message, error));
        }
    }
}

<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm.WpfClient/Services/IProductServiceAgent.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using WebApiSample.Mvvm.Client.Entities.Models;

namespace WebApiSample.Mvvm.WpfClient
{
    public interface IProductServiceAgent
    {
        Task<IEnumerable<Product>> GetProducts();
    }
}


<|start_filename|>Samples/VS2013/WebApiSample/WebApiSample.Service.Entities/Models/CustomerSetting.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using TrackableEntities;

namespace WebApiSample.Service.Entities.Models
{
    [Table("CustomerSetting")]
    public partial class CustomerSetting : ITrackable, IMergeable
    {
        [Key]
        [StringLength(5)]
        public string CustomerId { get; set; }

        [Required]
        [StringLength(50)]
        public string Setting { get; set; }

        public Customer Customer { get; set; }

		[NotMapped]
        public TrackingState TrackingState { get; set; }

		[NotMapped]
        public ICollection<string> ModifiedProperties { get; set; }

		[NotMapped]
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/Steps/BasicFeatureSteps.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Web.Http.SelfHost;
using TechTalk.SpecFlow;
using TrackableEntities.Client;
using TrackableEntities.EF.Tests.NorthwindModels;
using TrackableEntities.Tests.Acceptance.Helpers;
using TrackableEntities.Tests.Acceptance.WebHost;
using Xunit;

namespace TrackableEntities.Tests.Acceptance.Steps
{
    [Binding]
    public class BasicFeatureSteps
    {
        private HttpClient _client;
        private HttpSelfHostServer _server;
        private const int PortNumber = 56791;

        [BeforeScenario]
        public void Setup()
        {
            _client = WebHostClient.Create(PortNumber);
            _server = WebHostServer.Create(PortNumber);
            _server.OpenAsync().Wait();
        }

        [AfterScenario]
        public void TearDown()
        {
            _server.CloseAsync().Wait();
            _server.Dispose();
            _client.Dispose();
        }

        [Given(@"the following customers")]
        public void GivenTheFollowingCustomers(Table table)
        {
            var custIds = new List<string>();
            foreach (var row in table.Rows)
            {
                string custId = row["CustomerId"];
                string custName = row["CustomerName"];
                TestsHelper.EnsureTestCustomer(custId, custName);
                custIds.Add(custId);
            }
            ScenarioContext.Current.Add("CustIds", custIds);
        }

        [Given(@"the following customer orders")]
        public void GivenTheFollowingOrders(Table table)
        {
            var orders = new List<Order>();
            foreach (var row in table.Rows)
            {
                string custId = row["CustomerId"];
                TestsHelper.EnsureTestCustomer(custId, "Test Customer " + custId);
                var order = TestsHelper.EnsureTestOrder(custId);
                orders.Add(order);
            }
            ScenarioContext.Current.Add("CustOrders", orders);
        }

        [Given(@"the following new customer orders")]
        public void GivenTheFollowingNewCustomerOrders(Table table)
        {
            var orders = new List<ClientEntities.Order>();
            foreach (var row in table.Rows)
            {
                string custId = row["CustomerId"];
                int[] productIds = TestsHelper.CreateTestProducts();
                ScenarioContext.Current.Add("ProductIds", productIds);
                var clientOrder = EntityExtensions.CreateNewOrder(custId, productIds);
                orders.Add(clientOrder);
            }
            ScenarioContext.Current.Add("NewCustOrders", orders);
        }

        [Given(@"the following existing customer orders")]
        public void GivenTheFollowingExistingCustomerOrders(Table table)
        {
            var orders = new List<ClientEntities.Order>();
            foreach (var row in table.Rows)
            {
                string custId = row["CustomerId"];
                TestsHelper.EnsureTestCustomer(custId, "Test Customer " + custId);
                int[] productIds = TestsHelper.CreateTestProducts();
                ScenarioContext.Current.Add("ProductIds", productIds);
                var order = TestsHelper.CreateTestOrder(custId, productIds);
                orders.Add(order.ToClientEntity());
            }
            ScenarioContext.Current.Add("ExistingCustOrders", orders);
        }

        [Given(@"the order is modified")]
        public void GivenTheOrderIsModified()
        {
            var order = ScenarioContext.Current.Get<List<ClientEntities.Order>>("ExistingCustOrders").First();
            var changeTracker = new ChangeTrackingCollection<ClientEntities.Order>(order);
            ScenarioContext.Current.Add("DeletedDetail", order.OrderDetails[1]);
            int[] productIds = ScenarioContext.Current.Get<int[]>("ProductIds");
            var addedDetail = new ClientEntities.OrderDetail
            {
                OrderId = order.OrderId,
                ProductId = productIds[3],
                Quantity = 15,
                UnitPrice = 30
            };
            ScenarioContext.Current.Add("AddedDetail", addedDetail);
            order.OrderDate = order.OrderDate.AddDays(1);
            order.OrderDetails[0].UnitPrice++;
            order.OrderDetails.RemoveAt(1);
            order.OrderDetails.Add(addedDetail);
            ScenarioContext.Current.Add("ChangeTracker", changeTracker);
        }

        [Given(@"order details are added")]
        public void GivenOrderDetailsAreAdded()
        {
            var order = ScenarioContext.Current.Get<List<ClientEntities.Order>>("ExistingCustOrders").First();
            var changeTracker = new ChangeTrackingCollection<ClientEntities.Order>(order);
            int[] productIds = ScenarioContext.Current.Get<int[]>("ProductIds");
            var addedDetail1 = new ClientEntities.OrderDetail
            {
                OrderId = order.OrderId,
                ProductId = productIds[3],
                Quantity = 15,
                UnitPrice = 30
            };
            var addedDetail2 = new ClientEntities.OrderDetail
            {
                OrderId = order.OrderId,
                ProductId = productIds[4],
                Quantity = 20,
                UnitPrice = 40
            };
            ScenarioContext.Current.Add("AddedDetail1", addedDetail1);
            ScenarioContext.Current.Add("AddedDetail2", addedDetail2);
            order.OrderDetails.Add(addedDetail1);
            order.OrderDetails.Add(addedDetail2);
            ScenarioContext.Current.Add("ChangeTracker", changeTracker);
        }
        
        [When(@"I submit a GET request for customers")]
        public void WhenISubmitGetRequestForCustomers()
        {
            const string request = "api/Customer";
            var response = _client.GetAsync(request).Result;
            response.EnsureSuccessStatusCode();
            var result = response.Content.ReadAsAsync<IEnumerable<ClientEntities.Customer>>().Result.ToList();
            ScenarioContext.Current.Add("CustomersResult", result);
        }

        [When(@"I submit a GET request for customer orders")]
        public void WhenISubmitGetRequestForCustomerOrders()
        {
            var order = ScenarioContext.Current.Get<List<Order>>("CustOrders").First();
            string request = "api/Order?customerId=" + order.CustomerId;
            var response = _client.GetAsync(request).Result;
            response.EnsureSuccessStatusCode();
            var result = response.Content.ReadAsAsync<IEnumerable<ClientEntities.Order>>().Result.ToList();
            ScenarioContext.Current.Add("CustomerOrdersResult", result);
        }

        [When(@"I submit a GET request for an order")]
        public void WhenISubmitGetRequestForAnOrder()
        {
            var order = ScenarioContext.Current.Get<List<Order>>("CustOrders").First();
            string request = "api/Order/" + order.OrderId;
            var response = _client.GetAsync(request).Result;
            response.EnsureSuccessStatusCode();
            var orderResult = response.Content.ReadAsAsync<ClientEntities.Order>().Result;
            var result = new List<ClientEntities.Order> { orderResult };
            ScenarioContext.Current.Add("CustomerOrdersResult", result);
        }

        [When(@"I submit a POST to create an order")]
        public void WhenISubmitPostToCreateAnOrder()
        {
            var clientOrder = ScenarioContext.Current.Get<List<ClientEntities.Order>>("NewCustOrders").First();
            string request = "api/Order";
            var response = _client.PostAsJsonAsync(request, clientOrder).Result;
            response.EnsureSuccessStatusCode();
            var orderResult = response.Content.ReadAsAsync<ClientEntities.Order>().Result;
            var result = new List<ClientEntities.Order> { orderResult };
            ScenarioContext.Current.Add("CustomerOrdersResult", result);
        }

        [When(@"I submit a PUT to modify an order")]
        public void WhenISubmitPutToModifyAnOrder()
        {
            var clientOrder = ScenarioContext.Current.Get<List<ClientEntities.Order>>("ExistingCustOrders").First();
            var changeTracker = ScenarioContext.Current.Get<ChangeTrackingCollection<ClientEntities.Order>>("ChangeTracker");
            var clonedOrder = changeTracker.Clone()[0];
            ScenarioContext.Current["ExistingCustOrders"] = new List<ClientEntities.Order> { clonedOrder };
            var changedOrder = changeTracker.GetChanges().SingleOrDefault();

            string request = "api/Order";
            var response = _client.PutAsJsonAsync(request, changedOrder).Result;
            response.EnsureSuccessStatusCode();
            var orderResult = response.Content.ReadAsAsync<ClientEntities.Order>().Result;
            
            changeTracker.MergeChanges(orderResult);
            ScenarioContext.Current.Add("CustomerOrdersResult", new List<ClientEntities.Order>{ clientOrder});
        }

        [When(@"I submit a DELETE to delete an order")]
        public void WhenISubmitDeleteToDeleteAnOrder()
        {
            var clientOrder = ScenarioContext.Current.Get<List<ClientEntities.Order>>("ExistingCustOrders").First();
            string request = "api/Order/" + clientOrder.OrderId;
            var response = _client.DeleteAsync(request);
            response.Result.EnsureSuccessStatusCode();
        }
        
        [Then(@"the request should return the customers")]
        public void ThenTheRequestShouldReturnTheCustomers()
        {
            var custId1 = ScenarioContext.Current.Get<List<string>>("CustIds")[0];
            var custId2 = ScenarioContext.Current.Get<List<string>>("CustIds")[1];
            var result = ScenarioContext.Current.Get<List<ClientEntities.Customer>>("CustomersResult");
            Assert.True(result.Any(c => c.CustomerId == custId1));
            Assert.True(result.Any(c => c.CustomerId == custId2));
        }

        [Then(@"the request should return the orders")]
        public void ThenTheRequestShouldReturnTheOrders()
        {
            var result = ScenarioContext.Current.Get<List<ClientEntities.Order>>("CustomerOrdersResult");
            var orders = ScenarioContext.Current.Get<List<Order>>("CustOrders");
            foreach (var order in orders)
            {
                Assert.True(result.Any(o => o.OrderId == order.OrderId));
            }
        }

        [Then(@"the request should return the new order")]
        public void ThenTheRequestShouldReturnTheNewOrders()
        {
            var result = ScenarioContext.Current.Get<List<ClientEntities.Order>>("CustomerOrdersResult").Single();
            Assert.True(result.OrderId > 0);
        }

        [Then(@"the request should return the modified order")]
        public void ThenTheRequestShouldReturnTheModifiedOrder()
        {
            var modifiedOrder = ScenarioContext.Current.Get<List<ClientEntities.Order>>("ExistingCustOrders").Single();
            var updatedOrder = ScenarioContext.Current.Get<List<ClientEntities.Order>>("CustomerOrdersResult").Single();
            var addedDetail = ScenarioContext.Current.Get<ClientEntities.OrderDetail>("AddedDetail");
            var deletedDetail = ScenarioContext.Current.Get<ClientEntities.OrderDetail>("DeletedDetail");

            Assert.Equal(modifiedOrder.OrderDate, updatedOrder.OrderDate);
            Assert.Equal(modifiedOrder.OrderDetails[0].UnitPrice, updatedOrder.OrderDetails[0].UnitPrice);
            Assert.True(updatedOrder.OrderDetails.Any(d => d.ProductId == addedDetail.ProductId));
            Assert.False(updatedOrder.OrderDetails.Any(d => d.ProductId == deletedDetail.ProductId));
        }

        [Then(@"the request should return the added order details")]
        public void ThenTheRequestShouldReturnTheAddedOrderDetails()
        {
            var modifiedOrder = ScenarioContext.Current.Get<List<ClientEntities.Order>>("ExistingCustOrders").Single();
            var updatedOrder = ScenarioContext.Current.Get<List<ClientEntities.Order>>("CustomerOrdersResult").Single();
            var addedDetail1 = ScenarioContext.Current.Get<ClientEntities.OrderDetail>("AddedDetail1");
            var addedDetail2 = ScenarioContext.Current.Get<ClientEntities.OrderDetail>("AddedDetail2");

            Assert.Equal(modifiedOrder.OrderDetails[0].UnitPrice, updatedOrder.OrderDetails[0].UnitPrice);
            Assert.True(updatedOrder.OrderDetails.Any(d => d.ProductId == addedDetail1.ProductId));
            Assert.True(updatedOrder.OrderDetails.Any(d => d.ProductId == addedDetail2.ProductId));
        }
        
        [Then(@"the order should be deleted")]
        public void ThenTheOrderShouldBeDeleted()
        {
            var clientOrder = ScenarioContext.Current.Get<List<ClientEntities.Order>>("ExistingCustOrders").First();
            string request = "api/Order/" + clientOrder.OrderId;
            var response = _client.GetAsync(request).Result;
            Assert.False(response.IsSuccessStatusCode);
        }
    }
}


<|start_filename|>Source/TrackableEntities.Common/IMergeable.cs<|end_filename|>
﻿using System;

namespace TrackableEntities
{
    /// <summary>
    /// Provides an EntityIdentifier for correlation when merging changes.
    /// </summary>
    public interface IMergeable
    {
        /// <summary>
        /// Identifier used for correlation with MergeChanges.
        /// </summary>
        Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/ClientEntities/Category.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using TrackableEntities.Client;

namespace TrackableEntities.Tests.Acceptance.ClientEntities
{
    [JsonObject(IsReference = true)]
    public class Category : EntityBase
    {
        private int _categoryId;
        public int CategoryId
        {
            get { return _categoryId; }
            set
            {
                if (value == _categoryId) return;
                _categoryId = value;
                NotifyPropertyChanged();
            }
        }

        private string _categoryName;
        public string CategoryName
        {
            get { return _categoryName; }
            set
            {
                if (value == _categoryName) return;
                _categoryName = value;
                NotifyPropertyChanged();
            }
        }

        private ChangeTrackingCollection<Product> _products;
        public ChangeTrackingCollection<Product> Products
        {
            get { return _products; }
            set
            {
                if (Equals(value, _products)) return;
                _products = value;
                NotifyPropertyChanged();
            }
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm.WpfClient/Views/CustomerView.xaml.cs<|end_filename|>
﻿using System;
using System.Windows;
using System.Windows.Controls;
using SimpleMvvmToolkit;
using WebApiSample.Mvvm.Client.Entities.Models;

namespace WebApiSample.Mvvm.WpfClient
{
    /// <summary>
    /// Interaction logic for CustomerView.xaml
    /// </summary>
    public partial class CustomerView : UserControl
    {
        private readonly CustomerOrdersViewModel _viewModel;

        public CustomerView()
        {
            InitializeComponent();
            _viewModel = (CustomerOrdersViewModel)LayoutRoot.DataContext;
            InitializeViewModel();
        }

        private void InitializeViewModel()
        {
            _viewModel.ErrorNotice += OnErrorNotice;
            _viewModel.CreateOrderNotice += OnCreateOrderNotice;
            _viewModel.ModifyOrderNotice += OnModifyOrderNotice;
            _viewModel.DeleteOrderNotice += OnDeleteOrderNotice;
            _viewModel.DeleteVerifiedNotice += OnDeleteVerifiedNotice;
        }

        private void OnDeleteVerifiedNotice(object sender, NotificationEventArgs eventArgs)
        {
            MessageBox.Show("Order has been deleted", "Order Deleted",
                MessageBoxButton.OK, MessageBoxImage.Information);
        }

        private void OnCreateOrderNotice(object sender, NotificationEventArgs<Order> eventArgs)
        {
            // Create order view model and view
            var orderDetail = new OrderDetailView(eventArgs.Data);
            orderDetail.Owner = Window.GetWindow(this);

            // Show order detail dialog
            if (orderDetail.ShowDialog() == false) return;

            // Add new order
            _viewModel.AddNewOrder(orderDetail.ViewModel.Model);
        }

        private void OnModifyOrderNotice(object sender, NotificationEventArgs<Order> eventArgs)
        {
            // Create order view model and view
            var orderDetail = new OrderDetailView(eventArgs.Data);
            orderDetail.Owner = Window.GetWindow(this);

            // Show order detail dialog
            orderDetail.ShowDialog();
        }

        private void OnDeleteOrderNotice(object sender, NotificationEventArgs<Order, bool> eventArgs)
        {
            // Prompt user to delete order
            if (MessageBox.Show("Do you wish to delete this order?", "Delete Order",
                MessageBoxButton.OKCancel, MessageBoxImage.Question) == MessageBoxResult.OK)
            {
                eventArgs.Completed(true);
            }
        }

        private void OnErrorNotice(object sender, NotificationEventArgs<Exception> eventArgs)
        {
            MessageBox.Show(eventArgs.Data.Message, "Error");
        }

        private void OnUnloaded(object sender, RoutedEventArgs e)
        {
            _viewModel.ErrorNotice -= OnErrorNotice;
            _viewModel.CreateOrderNotice -= OnCreateOrderNotice;
            _viewModel.ModifyOrderNotice -= OnModifyOrderNotice;
            _viewModel.DeleteOrderNotice -= OnDeleteOrderNotice;
        }
    }
}


<|start_filename|>Extensions/Common/Wizards/TemplateWizardHarness/Program.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using ItemTemplateParametersWizard;
using TrackableEntities.ItemWizard;

namespace TemplateWizardHarness
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            // Get model types
            List<ModelTypeInfo> modelTypes = GetModelTypes();

            int dialogType = 0;
            do
            {
                // Prompt for dialog type
                Console.WriteLine("\nSelect Dialog:\r\n\tWCF Service Type {1},\r\n\tEntity Controller {2}, " +
                    "\r\n\tEntity Repo Class {3},\r\n\tEntity Repo Interface {4}");
                if (!int.TryParse(Console.ReadLine(), out dialogType)) return;

                // Show dialog
                Form dialog = GetTypesDialog(modelTypes, dialogType);
                if (dialog == null)
                {
                    Console.WriteLine("Incorrect selection: {0}", dialogType);
                    continue;
                };
                if (dialog.ShowDialog() == DialogResult.Cancel) continue;

                // Print dialog info
                PrintDialogInfo((IModelTypes)dialog);
            } while (dialogType > 0);
            Console.WriteLine("Press Enter to exit");
            Console.ReadLine();
        }

        private static void PrintDialogInfo(IModelTypes dialog)
        {
            ModelTypesDialogInfo info = dialog.ModelTypesDialogInfo;
            Console.WriteLine("BaseNamespace: {0}", info.BaseNamespace);
            Console.WriteLine("EntityName: {0}", info.EntityName);
            Console.WriteLine("EntitySetName: {0}", info.EntitySetName);
            Console.WriteLine("DbContextName: {0}", info.DbContextName);
        }

        private static Form GetTypesDialog(List<ModelTypeInfo> modelTypes, int dialogType)
        {
            switch (dialogType)
            {
                case 1:
                    return new ModelTypesContextDialog(modelTypes,
                        Dialogs.WcfServiceType.Title,
                        Dialogs.WcfServiceType.Message,
                        Dialogs.WcfServiceType.DialogWidth);
                case 2:
                    return new ModelTypesDialog(modelTypes,
                        Dialogs.EntityController.Title,
                        Dialogs.EntityController.Message,
                        Dialogs.EntityController.DialogWidth);
                case 3:
                    return new ModelTypesDialog(modelTypes,
                        Dialogs.EntityRepoClass.Title,
                        Dialogs.EntityRepoClass.Message,
                        Dialogs.EntityRepoClass.DialogWidth);
                case 4:
                    return new ModelTypesDialog(modelTypes,
                        Dialogs.EntityRepoInterface.Title,
                        Dialogs.EntityRepoInterface.Message,
                        Dialogs.EntityRepoInterface.DialogWidth);
                default:
                    return null;
            }
        }

        static List<ModelTypeInfo> GetModelTypes()
        {
            const string entitiesAsmName = "TemplateWizard.Service.Entities.dll";
            var dirName = new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName;
            string asmLocation = Path.Combine(dirName, entitiesAsmName);
            return ModelReflectionHelper.GetModelTypes(new FileInfo(asmLocation));
        }
    }
}


<|start_filename|>Samples/VS2013/WcfSample/WcfSample.Service.Core/OrderService.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.ServiceModel;
using System.Threading.Tasks;
using TrackableEntities;
using TrackableEntities.Common;
using TrackableEntities.EF6;
using WcfSample.Shared.Entities.Net45.Contexts;
using WcfSample.Shared.Entities.Net45.Models;

namespace WcfSample.Service.Core
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class OrderService : IOrderService, IDisposable
    {
        private readonly NorthwindSlim _dbContext;

        public OrderService()
        {
            _dbContext = new NorthwindSlim();
        }

        public async Task<IEnumerable<Order>> GetOrders()
        {
            IEnumerable<Order> orders = await _dbContext.Orders
                .Include(o => o.Customer)
                .Include("OrderDetails.Product")
                .ToListAsync();
            return orders;
        }

        public async Task<IEnumerable<Order>> GetCustomerOrders(string customerId)
        {
            IEnumerable<Order> orders = await _dbContext.Orders
                .Include(o => o.Customer)
                .Include("OrderDetails.Product")
                .Where(o => o.CustomerId == customerId)
                .ToListAsync();
            return orders;
        }

        public async Task<Order> GetOrder(int id)
        {
            Order order = await _dbContext.Orders
                .Include(o => o.Customer)
                .Include("OrderDetails.Product")
                .SingleOrDefaultAsync(o => o.OrderId == id);
            return order;
        }

        public async Task<Order> CreateOrder(Order order)
        {
            // Mark order as added
            order.TrackingState = TrackingState.Added;
            _dbContext.ApplyChanges(order);

            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateException updateEx)
            {
                throw new FaultException(updateEx.Message);
            }

            // Load related entities and accept changes
            await _dbContext.LoadRelatedEntitiesAsync(order);
            order.AcceptChanges();
            return order;
        }

        public async Task<Order> UpdateOrder(Order order)
        {
            // Update entity state
            _dbContext.ApplyChanges(order);

            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException updateEx)
            {
                throw new FaultException(updateEx.Message);
            }

            // Load related entities, accept changes and return updated order
            await _dbContext.LoadRelatedEntitiesAsync(order);
            order.AcceptChanges();
            return order;
        }

        public async Task<bool> DeleteOrder(int id)
        {
            // Retrieve order to be deleted
            Order order = await _dbContext.Orders
                .Include(o => o.OrderDetails) // Include details
                .SingleOrDefaultAsync(c => c.OrderId == id);
            if (order == null)
                return false;

            // Mark as deleted
            order.TrackingState = TrackingState.Deleted;
            _dbContext.ApplyChanges(order);

            try
            {
                await _dbContext.SaveChangesAsync();
                return true;
            }
            catch (DbUpdateConcurrencyException updateEx)
            {
                throw new FaultException(updateEx.Message);
            }
        }

        public void Dispose()
        {
            var dispose = _dbContext as IDisposable;
            if (dispose != null)
            {
                _dbContext.Dispose();
            }
        }
    }
}


<|start_filename|>Source/TrackableEntities.Client/PortableReflectionHelper.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace TrackableEntities.Client
{
    /// <summary>
    /// Reflection helper singleton class.
    ///
    /// Lists all functions (defines the contract) which must be implemented by the Impl-class,
    /// and ensures that all Impl-classes implement the identical interface.
    /// 
    /// The actual Impl-class is chosen depending on the conditional compiler #define's.
    /// 
    /// Should there become a need in the future for yet another varying reflection code,
    /// it is highly recommended to extend this class (together with Impl-subclasses) instead
    /// of inlining the #if-#else-#endif logic in the regular TE code.
    /// </summary>
    internal abstract class PortableReflectionHelper
    {
        #region Single Instance

        private static Lazy<PortableReflectionHelper> _inst =
            new Lazy<PortableReflectionHelper>(() => new PortableReflectionHelperImpl(), true);

        public static PortableReflectionHelper Instance
        {
            get { return _inst.Value; }
        }

        #endregion Single Instance

        public abstract bool IsAssignable(Type type, Type from);

        public abstract Type GetBaseType(Type type);

        public abstract Type[] GetGenericArguments(Type type);

        public abstract PropertyInfo GetProperty(Type type, string propertyName);

        public abstract IEnumerable<PropertyInfo> GetProperties(Type type);

        public abstract IEnumerable<PropertyInfo> GetPrivateInstanceProperties(Type type);

        public abstract IEnumerable<MethodInfo> GetPrivateInstanceMethods(Type type);

        public abstract MethodInfo GetMethodInfo(Delegate del);
    }

#if SILVERLIGHT || NET40

    internal class PortableReflectionHelperImpl : PortableReflectionHelper
    {
        public override bool IsAssignable(Type type, Type from)
        {
            return type.IsAssignableFrom(from);
        }

        public override Type GetBaseType(Type type)
        {
            return type.BaseType;
        }

        public override Type[] GetGenericArguments(Type type)
        {
            return type.GetGenericArguments();
        }

        public override PropertyInfo GetProperty(Type type, string propertyName)
        {
            return type.GetProperty(propertyName);
        }

        public override IEnumerable<PropertyInfo> GetProperties(Type type)
        {
            return type.GetProperties();
        }

        public override IEnumerable<PropertyInfo> GetPrivateInstanceProperties(Type type)
        {
            return type.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic);
        }

        public override IEnumerable<MethodInfo> GetPrivateInstanceMethods(Type type)
        {
            return type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic);
        }

        public override MethodInfo GetMethodInfo(Delegate del)
        {
            return del.Method;
        }
    }

#else

    internal class PortableReflectionHelperImpl : PortableReflectionHelper
    {
        public override bool IsAssignable(Type type, Type from)
        {
            return type.GetTypeInfo().IsAssignableFrom(from.GetTypeInfo());
        }

        public override Type GetBaseType(Type type)
        {
            return type.GetTypeInfo().BaseType;
        }

        public override Type[] GetGenericArguments(Type type)
        {
            return type.GetTypeInfo().GenericTypeArguments;
        }

        public override PropertyInfo GetProperty(Type type, string propertyName)
        {
            return type.GetTypeInfo().GetDeclaredProperty(propertyName);
        }

        public override IEnumerable<PropertyInfo> GetProperties(Type type)
        {
            return type
                .BaseTypes()
                .SelectMany(t => t.GetTypeInfo().DeclaredProperties)
                .Where(p => !p.GetMethod.IsPrivate);
        }

        public override IEnumerable<PropertyInfo> GetPrivateInstanceProperties(Type type)
        {
            return type
                .GetTypeInfo()
                .DeclaredProperties
                .Where(p => !p.GetMethod.IsStatic && p.GetMethod.IsPrivate);
        }

        public override IEnumerable<MethodInfo> GetPrivateInstanceMethods(Type type)
        {
            return type
                .GetTypeInfo()
                .DeclaredMethods
                .Where(m => !m.IsStatic && m.IsPrivate);
        }

        public override MethodInfo GetMethodInfo(Delegate del)
        {
            return del.GetMethodInfo();
        }
    }

#endif
}


<|start_filename|>Extensions/Common/Wizards/EntitiesSelectionWizard/EntitiesSelection.cs<|end_filename|>
﻿using System;

namespace EntitiesSelectionWizard
{
    [Flags]
    public enum EntitiesSelection
    {
        None = 0,
        Client = 1,
        Service = 2,
        ClientService = 4,
        Shared = 8,
        Portable = 16,
        DotNet45 = 32
    }
}


<|start_filename|>Build/Scripts/TrackableEntities.CodeTemplates.cmd<|end_filename|>
@echo On
set debug=%1

REM Set Variables:
set version=%PackageVersion%
set name=TrackableEntities.CodeTemplates
set source=Extensions\Templates\%name%
set output=Build\Output\%name%

rem Client.Portable
set ext=Client.Portable

REM Copy:
if "%debug%"=="1" pause
mkdir "%output%\%name%.%ext%"
xcopy "%source%.%ext%\Content" "%output%\%name%.%ext%\Content\" /e /y
xcopy "%source%.%ext%\tools" "%output%\%name%.%ext%\tools\" /e /y
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit

REM Package:
if "%debug%"=="1" pause
xcopy "%source%.%ext%\%name%.%ext%.nuspec" "%output%\%name%.%ext%\" /y
Source\.nuget\nuget.exe pack "%output%\%name%.%ext%\%name%.%ext%.nuspec" -o "%output%\%name%.%ext%" -p PackageVersion="%version%"
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit

rem Client.Net45
set ext=Client.Net45

REM Copy:
if "%debug%"=="1" pause
mkdir "%output%\%name%.%ext%"
xcopy "%source%.%ext%\Content" "%output%\%name%.%ext%\Content\" /e /y
xcopy "%source%.%ext%\tools" "%output%\%name%.%ext%\tools\" /e /y
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit

REM Package:
if "%debug%"=="1" pause
xcopy "%source%.%ext%\%name%.%ext%.nuspec" "%output%\%name%.%ext%\" /y
Source\.nuget\nuget.exe pack "%output%\%name%.%ext%\%name%.%ext%.nuspec" -o "%output%\%name%.%ext%" -p PackageVersion="%version%"
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit

rem Service.Net45
set ext=Service.Net45

REM Copy:
if "%debug%"=="1" pause
mkdir "%output%\%name%.%ext%"
xcopy "%source%.%ext%\Content" "%output%\%name%.%ext%\Content\" /e /y
xcopy "%source%.%ext%\tools" "%output%\%name%.%ext%\tools\" /e /y
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit

REM Package:
if "%debug%"=="1" pause
xcopy "%source%.%ext%\%name%.%ext%.nuspec" "%output%\%name%.%ext%\" /y
Source\.nuget\nuget.exe pack "%output%\%name%.%ext%\%name%.%ext%.nuspec" -o "%output%\%name%.%ext%" -p PackageVersion="%version%"
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit

rem Shared.Net45
set ext=Shared.Net45

REM Copy:
if "%debug%"=="1" pause
mkdir "%output%\%name%.%ext%"
xcopy "%source%.%ext%\Content" "%output%\%name%.%ext%\Content\" /e /y
xcopy "%source%.%ext%\tools" "%output%\%name%.%ext%\tools\" /e /y
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit

REM Package:
if "%debug%"=="1" pause
xcopy "%source%.%ext%\%name%.%ext%.nuspec" "%output%\%name%.%ext%\" /y
Source\.nuget\nuget.exe pack "%output%\%name%.%ext%\%name%.%ext%.nuspec" -o "%output%\%name%.%ext%" -p PackageVersion="%version%"
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit

rem Shared.Portable
set ext=Shared.Portable

REM Copy:
if "%debug%"=="1" pause
mkdir "%output%\%name%.%ext%"
xcopy "%source%.%ext%\Content" "%output%\%name%.%ext%\Content\" /e /y
xcopy "%source%.%ext%\tools" "%output%\%name%.%ext%\tools\" /e /y
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit

REM Package:
if "%debug%"=="1" pause
xcopy "%source%.%ext%\%name%.%ext%.nuspec" "%output%\%name%.%ext%\" /y
Source\.nuget\nuget.exe pack "%output%\%name%.%ext%\%name%.%ext%.nuspec" -o "%output%\%name%.%ext%" -p PackageVersion="%version%"
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit


<|start_filename|>Source/Tests/TrackableEntities.Client.Tests.Entities/NorthwindModels/PromotionalProduct.cs<|end_filename|>
﻿using System;
using Newtonsoft.Json;

namespace TrackableEntities.Client.Tests.Entities.NorthwindModels
{
    [JsonObject(IsReference = true)]
    public class PromotionalProduct : Product
    {
        private string _giftCode;
        public string PromoCode
        {
            get { return _giftCode; }
            set
            {
                if (value == _giftCode) return;
                _giftCode = value;
                NotifyPropertyChanged(() => PromoCode);
            }
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Inheritance/SampleWebApi.Inheritance.Shared.Entities/Contexts/NorthwindSlimDatabaseInitializer.cs<|end_filename|>
﻿using System;
using System.Data.Entity;
using SampleWebApi.Inheritance.Shared.Entities.Models;

namespace SampleWebApi.Inheritance.Shared.Entities.Contexts
{
    public class NorthwindSlimDatabaseInitializer : DropCreateDatabaseIfModelChanges<NorthwindSlimInheritance>
    {
        protected override void Seed(NorthwindSlimInheritance context)
        {
            AddCategories(context);
            AddProducts(context);
        }

        private void AddProducts(NorthwindSlimInheritance context)
        {
            context.Products.Add(new Product
            {
                ProductId = 1,
                CategoryId = 1,
                ProductName = "Chai",
                UnitPrice = 23M
            });
            context.Products.Add(new Product
            {
                ProductId = 2,
                CategoryId = 1,
                ProductName = "Chang",
                UnitPrice = 23M
            });
            context.Products.Add(new DiscontinuedProduct
            {
                ProductId = 3,
                CategoryId = 2,
                ProductName = "Aniseed Syrup",
                UnitPrice = 23M,
                DiscontinuedDate = DateTime.Today.Subtract(TimeSpan.FromDays(1))
            });
            context.Products.Add(new DiscontinuedProduct
            {
                ProductId = 4,
                CategoryId = 2,
                ProductName = "Chef Anton's Cajun Seasoning",
                UnitPrice = 23M,
                DiscontinuedDate = DateTime.Today.Subtract(TimeSpan.FromDays(2))
            });
        }

        private void AddCategories(NorthwindSlimInheritance context)
        {
            context.Categories.Add(new Category
            {
                CategoryId = 1,
                CategoryName = "Beverages"
            });
            context.Categories.Add(new Category
            {
                CategoryId = 2,
                CategoryName = "Condiments"
            });
            context.Categories.Add(new Category
            {
                CategoryId = 3,
                CategoryName = "Confections"
            });
            context.Categories.Add(new Category
            {
                CategoryId = 4,
                CategoryName = "Dairy Products"
            });
            context.Categories.Add(new Category
            {
                CategoryId = 5,
                CategoryName = "Grains/Cereals"
            });
            context.Categories.Add(new Category
            {
                CategoryId = 6,
                CategoryName = "Meat/Poultry"
            });
            context.Categories.Add(new Category
            {
                CategoryId = 7,
                CategoryName = "Produce"
            });
            context.Categories.Add(new Category
            {
                CategoryId = 7,
                CategoryName = "Seafood"
            });
        }
    }
}


<|start_filename|>Extensions/Common/Wizards/ItemTemplateParametersWizard/ModelTypesDialog.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace ItemTemplateParametersWizard
{
    public partial class ModelTypesDialog : Form, IModelTypes
    {
        private readonly List<ModelTypeInfo> _modelTypes;
        private readonly string _dialogTitle;
        private readonly string _dialogMessage;

        public ModelTypesDialog(List<ModelTypeInfo> modelTypes, 
            string dialogTitle, string dialogMessage, int dialogWidth)
        {
            Application.EnableVisualStyles();
            InitializeComponent();
            _modelTypes = modelTypes;
            _dialogTitle = dialogTitle;
            _dialogMessage = dialogMessage;
            Width = dialogWidth;
        }

        public ModelTypesDialogInfo ModelTypesDialogInfo { get; private set; }

        private void okButton_Click(object sender, EventArgs e)
        {
            ModelTypesDialogInfo = ModelTypesHelper.GetModelTypesInfo(entitySetTextBox,
                entityNameComboBox, null);
            if (ModelTypesDialogInfo == null) return;
            DialogResult = DialogResult.OK;
        }

        private void cancelButton_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.Cancel;
        }

        private void ModelTypesDialog_Load(object sender, EventArgs e)
        {
            bool setupValid = ModelTypesHelper.SetupUserInterface(
                _modelTypes, _dialogTitle, _dialogMessage, this,
                descriptionLabel, entityNameComboBox, null);
            if (!setupValid)
            {
                DialogResult = DialogResult.Cancel;
            }
        }

        private void ModelTypesDialog_Resize(object sender, EventArgs e)
        {
            PositionControl(descriptionLabel);
            PositionControl(buttonsPanel);
        }

        private void PositionControl(Control control)
        {
            var curHeight = control.Location.Y;
            control.Location = new Point(
            Width / 2 - control.Size.Width / 2, curHeight);
        }
    }
}


<|start_filename|>Source/Tests/TrackableEntities.Client.Tests.Entities/NorthwindModels/PriorityOrder.cs<|end_filename|>
﻿using System;
using Newtonsoft.Json;

namespace TrackableEntities.Client.Tests.Entities.NorthwindModels
{
    [JsonObject(IsReference = true)]
    public class PriorityOrder : Order
    {
        private string _priorityPlan;
        public string PriorityPlan
        {
            get { return _priorityPlan; }
            set
            {
                if (value == _priorityPlan) return;
                _priorityPlan = value;
                NotifyPropertyChanged(() => PriorityPlan);
            }
        }
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/Steps/RelationsFeatureSteps.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Web.Http.SelfHost;
using TechTalk.SpecFlow;
using TrackableEntities.Client;
using TrackableEntities.Common;
using TrackableEntities.Tests.Acceptance.ClientEntities;
using TrackableEntities.Tests.Acceptance.Helpers;
using TrackableEntities.Tests.Acceptance.WebHost;
using Xunit;

namespace TrackableEntities.Tests.Acceptance.Steps
{
    [Binding]
    public class RelationsFeatureSteps
    {
        private HttpClient _client;
        private HttpSelfHostServer _server;
        private const int PortNumber = 56792;

        [BeforeScenario]
        public void Setup()
        {
            _client = WebHostClient.Create(PortNumber);
            _server = WebHostServer.Create(PortNumber);
            _server.OpenAsync().Wait();
        }

        [AfterScenario]
        public void TearDown()
        {
            _server.CloseAsync().Wait();
            _server.Dispose();
            _client.Dispose();
        }

        [Given(@"the following new customer")]
        public void GivenTheFollowingNewCustomer(Table table)
        {
            ScenarioContext.Current.Pending();

            string custId = table.Rows[0]["CustomerId"];
            string custName = table.Rows[0]["CustomerName"];
            var customer = new Customer
            {
                CustomerId = custId,
                CustomerName = custName
            };
            ScenarioContext.Current.Add("Customer", customer);
        }

        [When(@"I submit a POST to create a customer")]
        public void WhenISubmitPostToCreateAnEntity()
        {
            ScenarioContext.Current.Pending();

            var customer = ScenarioContext.Current.Get<Customer>("Customer");
            var changeTracker = new ChangeTrackingCollection<Customer>(true) { customer };
            Customer result = _client.CreateEntity(customer);
            changeTracker.MergeChanges(result);
        }

        [When(@"I add a customer setting")]
        public void WhenIAddACustomerSetting()
        {
            ScenarioContext.Current.Pending();

            var customer = ScenarioContext.Current.Get<Customer>("Customer");
            customer.CustomerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Setting = " Test Setting",
                TrackingState = TrackingState.Added // Mark as added
            };
        }

        [When(@"I submit a PUT to update the customer")]
        public void WhenISubmitPutToUpdateTheCustomer()
        {
            ScenarioContext.Current.Pending();

            var customer = ScenarioContext.Current.Get<Customer>("Customer");
            _client.UpdateTEntity(customer);
            customer.AcceptChanges();
        }
        
        [Then(@"the request should return the new customer")]
        public void ThenTheRequestShouldReturnTheNewCustomer()
        {
            ScenarioContext.Current.Pending();

            var customer = ScenarioContext.Current.Get<Customer>("Customer");
            Customer result = _client.GetEntity<Customer, string>(customer.CustomerId);
            Assert.NotNull(result);
            Assert.Equal(customer.CustomerName, result.CustomerName);
            Assert.Equal(customer.CustomerSetting.Setting, result.CustomerSetting.Setting);
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Relations/WebApiSample.ConsoleClient/Program.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using TrackableEntities;
using TrackableEntities.Client;
using TrackableEntities.Common;
using WebApiSample.Client.Entities.Models;

namespace WebApiSample.Client.ConsoleApp
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine("Press Enter to start");
            Console.ReadLine();

            // TODO: Address for Web API service (replace port number)
            const string serviceBaseAddress = "http://localhost:" + "58540" + "/";
            var client = new HttpClient { BaseAddress = new Uri(serviceBaseAddress) };

            // Perform updates on a 1-1 property
            Console.WriteLine("\nPART A: One-to-One Relation: Customer.CustomerSetting");
            Console.WriteLine("Update 1-1 relation? {Y/N}");
            if (Console.ReadLine().ToUpper() == "Y")
                OneToOneRelation(client);

            // Perform updates on a M-1 property
            Console.WriteLine("\nPART B: Many-to-One Relation: Order.Customer");
            Console.WriteLine("Update M-1 relation? {Y/N}");
            if (Console.ReadLine().ToUpper() == "Y")
                ManyToOneRelation(client);

            // Perform updates on a M-M property
            Console.WriteLine("\nPART C: Many-to-Many Relation: Employee.Territories");
            Console.WriteLine("Update M-M relation? {Y/N}");
            if (Console.ReadLine().ToUpper() == "Y")
                ManyToManyRelation(client);

            // Keep console open
            Console.WriteLine("Press any key to exit");
            Console.ReadKey(true);
        }

        private static void OneToOneRelation(HttpClient client)
        {
            Console.WriteLine("\nPress Enter to create a new customer");
            Console.ReadLine();

            // Create a new customer
            var customer = new Customer
            {
                CustomerId = "ABCDE",
                CompanyName = "Acme Company",
                ContactName = "<NAME>",
                City = "Dallas",
                Country = "USA"
            };

            // Add to change tracker to mark as Added
            var customerChangeTracker = new ChangeTrackingCollection<Customer>(true) { customer };

            // Insert customer and merge
            Customer updatedCustomer = CreateEntity(client, customer);
            customerChangeTracker.MergeChanges(updatedCustomer);
            PrintCustomer(customer);

            Console.WriteLine("\nPress Enter to add a new setting");
            Console.ReadLine();

            // Add a new customer setting
            // NOTE: To add a 1-1 property, you must manually mark it as Added. 
            customer.CustomerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Setting = " Test Setting",
                TrackingState = TrackingState.Added // Mark as added
            };

            // Update customer, then accept changes
            updatedCustomer = UpdateEntity(client, customer);
            Console.WriteLine("\tCustomer setting added: {0}",
                updatedCustomer.CustomerSetting != null);
            customer.AcceptChanges();
            PrintCustomer(customer);

            // Add new customer setting
            Console.WriteLine("\nPress Enter to modify the setting");
            Console.ReadLine();

            // Modify customer setting
            var newSetting = customer.CustomerSetting.Setting += " - Changed";

            // Update customer, then accept changes
            updatedCustomer = UpdateEntity(client, customer);
            Console.WriteLine("\tCustomer setting modified: {0}", 
                updatedCustomer.CustomerSetting.Setting == newSetting);
            customer.AcceptChanges();
            PrintCustomer(customer);

            // Remove existing customer setting
            Console.WriteLine("\nPress Enter to remove the existing setting");
            Console.ReadLine();

            // Delete existing customer setting
            // NOTE: To remove a 1-1 property, you must manually mark it as Deleted. 
            customer.CustomerSetting.TrackingState = TrackingState.Deleted;

            // Update customer, then set 1-1 property to null
            updatedCustomer = UpdateEntity(client, customer);
            Console.WriteLine("\tCustomer setting removed: {0}",
                updatedCustomer.CustomerSetting == null);
            customer.CustomerSetting = null;
            PrintCustomer(customer);

            // Delete the customer
            Console.WriteLine("\nPress Enter to delete the customer");
            Console.ReadLine();
            DeleteEntity<Customer, string>(client, customer.CustomerId);

            // Verify order was deleted
            var deleted = VerifyEntityDeleted<Customer, string>(client, customer.CustomerId);
            Console.WriteLine(deleted ?
                "Customer was successfully deleted" :
                "Customer was NOT deleted");
        }

        private static void ManyToOneRelation(HttpClient client)
        {
            Console.WriteLine("\nPress Enter to create a new order for an existing customer");
            Console.ReadLine();

            // Create a new order for an existing customer
            var order = new Order {CustomerId = "ALFKI", OrderDate = DateTime.Today, ShippedDate = DateTime.Today.AddDays(1)};

            // Add to change tracker to mark as Added
            var orderChangeTracker = new ChangeTrackingCollection<Order>(true) {order};

            // Insert order and merge
            Order updatedOrder = CreateEntity(client, order);
            orderChangeTracker.MergeChanges(updatedOrder);
            PrintOrder(order);

            Console.WriteLine("\nPress Enter to add a new customer to the order");
            Console.ReadLine();

            // Create a new customer
            // NOTE: Marking customer as Added will create a NEW customer
            const string customerId = "WXYZ";
            var customer = new Customer
            {
                CustomerId = customerId,
                CompanyName = "Widget Company",
                ContactName = "<NAME>",
                City = "New York",
                Country = "USA",
                TrackingState = TrackingState.Added // Mark as added
            };
            order.Customer = customer; // new customer will be created
            order.CustomerId = customerId; // cust will be assigned to order

            // Update order, then accept changes
            updatedOrder = UpdateEntity(client, order);
            Console.WriteLine("\tOrder's customer added: {0}", updatedOrder.Customer != null);
            order.AcceptChanges();
            PrintOrder(order);
            PrintCustomer(order.Customer);

            Console.WriteLine("\nPress Enter to modify order's customer");
            Console.ReadLine();

            // Modify order customer
            var newCompanyName = order.Customer.CompanyName += " - Changed";

            // Update order, then accept changes
            UpdateEntity(client, order);
            var updatedCustomer = GetEntity<Customer, string>(client, customerId);
            Console.WriteLine("\tOrder customer's name modified: {0}",
                updatedCustomer.CompanyName == newCompanyName);
            customer.AcceptChanges();
            PrintCustomer(customer);

            // Delete the order and customer
            Console.WriteLine("\nPress Enter to delete the order and customer");
            Console.ReadLine();

            // Delete order and verify
            DeleteEntity<Order, int>(client, order.OrderId);
            var orderDeleted = VerifyEntityDeleted<Order, int>(client, order.OrderId);
            Console.WriteLine(orderDeleted ?
                "Order was successfully deleted" :
                "Order was NOT deleted");

            // Delete order and verify
            DeleteEntity<Customer, string>(client, customer.CustomerId);
            var customerDeleted = VerifyEntityDeleted<Customer, string>(client, customer.CustomerId);
            Console.WriteLine(customerDeleted ?
                "Customer was successfully deleted" :
                "Customer was NOT deleted");
        }

        private static void ManyToManyRelation(HttpClient client)
        {
            Console.WriteLine("\nPress Enter to create a new employee existing territory");
            Console.ReadLine();

            // Get existing territories
            var territory1 = GetEntity<Territory, string>(client, "01581");
            var territory2 = GetEntity<Territory, string>(client, "01730");
            var territory3 = GetEntity<Territory, string>(client, "01833");

            // Create a new employee
            var employee = new Employee
            {
                LastName = "Smith",
                FirstName = "John",
                BirthDate = DateTime.Parse("1979-12-09"),
                HireDate = DateTime.Parse("2001-05-01"),
                City = "Dallas",
                Country = "USA",
                Territories = new ChangeTrackingCollection<Territory>
                    {territory1, territory2, territory3}
            };

            // Add to change tracker to mark as Added
            var employeeChangeTracker = new ChangeTrackingCollection<Employee>(true) { employee };

            // Insert employee and merge
            Employee updatedEmployee = CreateEntity(client, employee);
            employeeChangeTracker.MergeChanges(updatedEmployee);
            PrintEmployee(employee);

            Console.WriteLine("\nPress Enter to modify, add and remove territories");
            Console.ReadLine();

            // Modify territory, remove territory, add existing territory
            var territory4 = GetEntity<Territory, string>(client, "02116");
            employee.Territories[1].TerritoryDescription += " - Changed";
            employee.Territories.RemoveAt(2);
            employee.Territories.Add(territory4);

            // Update employee, then merge changes
            var changedEmployee = employeeChangeTracker.GetChanges().SingleOrDefault();
            updatedEmployee = UpdateEntity(client, changedEmployee);
            employeeChangeTracker.MergeChanges(updatedEmployee);
            PrintEmployee(employee);

            // Delete the order and customer
            Console.WriteLine("\nPress Enter to delete the employee without deleting territories");
            Console.ReadLine();

            // Delete order and verify
            DeleteEntity<Employee, int>(client, employee.EmployeeId);
            var employeeDeleted = VerifyEntityDeleted<Employee, int>(client, employee.EmployeeId);
            Console.WriteLine(employeeDeleted ?
                "Employee was successfully deleted" :
                "Employee was NOT deleted");
            var removedTerritory = GetEntity<Territory, string>(client, "01833");
            Console.WriteLine("Removed territory '01833' still exists: {0}",
                removedTerritory != null);
        }

        #region Helper Methods

        private static IEnumerable<TEntity> GetEntities<TEntity>(HttpClient client)
        {
            string request = string.Format("api/{0}", typeof(TEntity).Name);
            var response = client.GetAsync(request).Result;
            response.EnsureSuccessStatusCode();
            var result = response.Content.ReadAsAsync<IEnumerable<TEntity>>().Result;
            return result;
        }

        private static TEntity GetEntity<TEntity, TKey>(HttpClient client, TKey id)
        {
            string request = string.Format("api/{0}/{1}", typeof(TEntity).Name, id);
            var response = client.GetAsync(request).Result;
            response.EnsureSuccessStatusCode();
            var result = response.Content.ReadAsAsync<TEntity>().Result;
            return result;
        }

        private static TEntity CreateEntity<TEntity>(HttpClient client, TEntity entity)
        {
            string request = string.Format("api/{0}", typeof(TEntity).Name);
            var response = client.PostAsJsonAsync(request, entity).Result;
            response.EnsureSuccessStatusCode();
            var result = response.Content.ReadAsAsync<TEntity>().Result;
            return result;
        }

        private static TEntity UpdateEntity<TEntity>(HttpClient client, TEntity entity)
        {
            string request = string.Format("api/{0}", typeof(TEntity).Name);
            var response = client.PutAsJsonAsync(request, entity).Result;
            response.EnsureSuccessStatusCode();
            var result = response.Content.ReadAsAsync<TEntity>().Result;
            return result;
        }

        private static void DeleteEntity<TEntity, TKey>(HttpClient client, TKey id)
        {
            string request = string.Format("api/{0}/{1}", typeof(TEntity).Name, id);
            var response = client.DeleteAsync(request);
            response.Result.EnsureSuccessStatusCode();
        }

        private static bool VerifyEntityDeleted<TEntity, TKey>(HttpClient client, TKey id)
        {
            string request = string.Format("api/{0}/{1}", typeof(TEntity).Name, id);
            var response = client.GetAsync(request).Result;
            if (response.IsSuccessStatusCode) return false;
            return true;
        }

        private static void PrintCustomer(Customer c)
        {
            Console.WriteLine("\t{0} {1} {2} {3} {4}",
                c.CustomerId,
                c.CompanyName,
                c.ContactName,
                c.City,
                c.CustomerSetting != null ? c.CustomerSetting.Setting : string.Empty);
        }

        private static void PrintOrder(Order o)
        {
            Console.WriteLine("\t{0} {1}",
                o.OrderId,
                o.OrderDate.GetValueOrDefault().ToShortDateString());
        }

        private static void PrintEmployee(Employee e)
        {
            Console.WriteLine("\t{0} {1} {2} {3} {4}",
                e.EmployeeId,
                e.FirstName,
                e.LastName,
                e.BirthDate.Value.ToShortDateString(),
                e.HireDate.Value.ToShortDateString());
            foreach (var t in e.Territories)
            {
                Console.WriteLine("\t\t{0} {1}",
                    t.TerritoryId,
                    t.TerritoryDescription);
            }
        }

        #endregion
    }
}


<|start_filename|>Extensions/Common/Wizards/TemplateWizard.Service.Entities/Models/Mapping/ProductMap.cs<|end_filename|>
using System.Data.Entity.ModelConfiguration;

namespace TemplateWizard.Service.Entities.Models.Mapping
{
    public class ProductMap : EntityTypeConfiguration<Product>
    {
        public ProductMap()
        {
            // Primary Key
            this.HasKey(t => t.ProductId);

            // Properties
            this.Property(t => t.ProductName)
                .IsRequired()
                .HasMaxLength(40);

            this.Property(t => t.RowVersion)
                .IsFixedLength()
                .HasMaxLength(8)
                .IsRowVersion();

            // Table & Column Mappings
            this.ToTable("Product");
            this.Property(t => t.ProductId).HasColumnName("ProductId");
            this.Property(t => t.ProductName).HasColumnName("ProductName");
            this.Property(t => t.CategoryId).HasColumnName("CategoryId");
            this.Property(t => t.UnitPrice).HasColumnName("UnitPrice");
            this.Property(t => t.Discontinued).HasColumnName("Discontinued");
            this.Property(t => t.RowVersion).HasColumnName("RowVersion");

            // Tracking Properties
			this.Ignore(t => t.TrackingState);
			this.Ignore(t => t.ModifiedProperties);

            // Relationships
            this.HasOptional(t => t.Category)
                .WithMany(t => t.Products)
                .HasForeignKey(d => d.CategoryId);

        }
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/ClientEntities/CustomerSetting.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using TrackableEntities.Client;

namespace TrackableEntities.Tests.Acceptance.ClientEntities
{
    [JsonObject(IsReference = true)]
    public class CustomerSetting : EntityBase
    {
        private string _customerId;
        public string CustomerId
        {
            get { return _customerId; }
            set
            {
                if (value == _customerId) return;
                _customerId = value;
                NotifyPropertyChanged();
            }
        }

        private string _setting;
        public string Setting
        {
            get { return _setting; }
            set
            {
                if (value == _setting) return;
                _setting = value;
                NotifyPropertyChanged();
            }
        }

        private Customer _customer;
        public Customer Customer
        {
            get { return _customer; }
            set
            {
                if (value == _customer) return;
                _customer = value;
                CustomerChangeTracker = _customer == null ? null
                    : new ChangeTrackingCollection<Customer> { _customer };
                NotifyPropertyChanged();
            }
        }
        private ChangeTrackingCollection<Customer> CustomerChangeTracker { get; set; }
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/Helpers/TestsHelper.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using TrackableEntities.EF.Tests;
using TrackableEntities.EF.Tests.NorthwindModels;
using TrackableEntities.Tests.Acceptance.Contexts;
using Xunit;

namespace TrackableEntities.Tests.Acceptance.Helpers
{
    internal static class TestsHelper
    {
        private const CreateDbOptions CreateNorthwindDbOptions = CreateDbOptions.DropCreateDatabaseIfModelChanges;

        public static NorthwindTestDbContext CreateNorthwindDbContext(CreateDbOptions createDbOptions)
        {
            // Create new context for all tests
            var context = new NorthwindTestDbContext(createDbOptions);
            Assert.True(context.Products.Count() >= 0);
            return context;
        }

        public static void EnsureTestCustomer(string customerId, string customerName)
        {
            using (var context = CreateNorthwindDbContext(CreateNorthwindDbOptions))
            {
                var customer = context.Customers
                    .SingleOrDefault(c => c.CustomerId == customerId);
                if (customer == null)
                {
                    customer = new Customer
                    {
                        CustomerId = customerId,
                        CustomerName = customerName
                    };
                    context.Customers.Add(customer);
                    context.SaveChanges();
                }
            }
        }

        public static Order EnsureTestOrder(string customerId)
        {
            using (var context = CreateNorthwindDbContext(CreateNorthwindDbOptions))
            {
                var order = context.Orders
                    .FirstOrDefault(o => o.CustomerId == customerId);
                if (order == null)
                {
                    int[] productIds = TestsHelper.CreateTestProducts();
                    order = CreateTestOrder(customerId, productIds);
                }
                return order;
            }
        }

        public static int[] CreateTestProducts()
        {
            using (var context = CreateNorthwindDbContext(CreateNorthwindDbOptions))
            {
                var category1 = new Category
                {
                    CategoryName = "Test Category 1"
                };
                var category2 = new Category
                {
                    CategoryName = "Test Category 2"
                };
                var product1 = new Product
                {
                    ProductName = "Test Product 1",
                    UnitPrice = 10M,
                    Category = category1
                };
                var product2 = new Product
                {
                    ProductName = "Test Product 2",
                    UnitPrice = 20M,
                    Category = category2
                };
                var product3 = new Product
                {
                    ProductName = "Test Product 3",
                    UnitPrice = 20M,
                    Category = category1
                };
                var product4 = new Product
                {
                    ProductName = "Test Product 4",
                    UnitPrice = 20M,
                    Category = category2
                };
                var product5 = new Product
                {
                    ProductName = "Test Product 5",
                    UnitPrice = 20M,
                    Category = category2
                };


                context.Products.Add(product1);
                context.Products.Add(product2);
                context.Products.Add(product3);
                context.Products.Add(product4);
                context.Products.Add(product5);
                context.SaveChanges();
                int[] ids =
                {
                    product1.ProductId,
                    product2.ProductId,
                    product3.ProductId,
                    product4.ProductId,
                    product5.ProductId,
                };
                return ids;
            }
        }

        public static Order CreateTestOrder(string customerId, int[] productIds)
        {
            using (var context = CreateNorthwindDbContext(CreateNorthwindDbOptions))
            {
                var detail1 = new OrderDetail { ProductId = productIds[0], Quantity = 11, UnitPrice = 11M };
                var detail2 = new OrderDetail { ProductId = productIds[1], Quantity = 12, UnitPrice = 12M };
                var detail3 = new OrderDetail { ProductId = productIds[2], Quantity = 13, UnitPrice = 13M };
                var order = new Order
                {
                    OrderDate = DateTime.Today,
                    CustomerId = customerId,
                    OrderDetails = new List<OrderDetail>
                    {
                        detail1,
                        detail2,
                        detail3
                    }
                };

                context.Orders.Add(order);
                context.SaveChanges();
                return order;
            }
        }
    }
}


<|start_filename|>Source/Tests/TrackableEntities.EF.5.Tests/NorthwindModels/Territory.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TrackableEntities.EF.Tests.NorthwindModels
{
    public partial class Territory : ITrackable
    {
        public Territory()
        {
            Employees = new List<Employee>();
            Customers = new List<Customer>();
        }

        [Key]
        public string TerritoryId { get; set; }
        public string TerritoryDescription { get; set; }
        public List<Employee> Employees { get; set; }
        public List<Customer> Customers { get; set; }
        public int? AreaId { get; set; }
        [ForeignKey("AreaId")]
        public Area Area { get; set; }

        [NotMapped]
        public TrackingState TrackingState { get; set; }
        [NotMapped]
        public ICollection<string> ModifiedProperties { get; set; }
    }
}


<|start_filename|>Source/TrackableEntities.Patterns.EF.6/Repository.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.Data.Entity;
using System.Threading;
using System.Threading.Tasks;
using TrackableEntities.EF6;

namespace TrackableEntities.Patterns.EF6
{
    /// <summary>
    /// Generic repository with basic operations.
    /// </summary>
    /// <typeparam name="TEntity">Entity type for the repository.</typeparam>
    public abstract class Repository<TEntity> : IRepository<TEntity>, IRepositoryAsync<TEntity>
        where TEntity : class, ITrackable
    {
        /// <summary>
        /// Creates a new Repository.
        /// </summary>
        protected Repository() { }

        /// <summary>
        /// Creates a new Repository.
        /// </summary>
        /// <param name="context">Entity Framework DbContext-derived class.</param>
        protected Repository(DbContext context)
        {
            Context = context;
        }

        /// <summary>
        /// Gets and sets the DbContext for the repository.
        /// </summary>
        protected DbContext Context { get; set; }

        /// <summary>
        /// Gets the DbSet for the respository
        /// </summary>
        protected DbSet<TEntity> Set
        {
            get
            {
                return Context.Set<TEntity>();
            }
        }

        /// <summary>
        /// Finds an entity with the given primary key values. If no entity is found, then null is returned.
        /// </summary>
        /// <param name="keyValues">The values of the primary key for the entity to be found.</param>
        /// <returns>The entity found, or null.</returns>
        public virtual TEntity Find(params object[] keyValues)
        {
            return Set.Find(keyValues);
        }

        /// <summary>
        /// Inserts a new entity into the repository.
        /// </summary>
        /// <param name="entity">Entity to insert.</param>
        public virtual void Insert(TEntity entity)
        {
            entity.TrackingState = TrackingState.Added;
            Context.ApplyChanges(entity);
        }

        /// <summary>
        /// Updates an existing entity in the repository.
        /// </summary>
        /// <param name="entity">Entity to update.</param>
        public virtual void Update(TEntity entity)
        {
            Context.ApplyChanges(entity);
        }

        /// <summary>
        /// <para>Removes an entity from the respository.</para>
        /// <para>Override to include child entities in delete operation.</para>
        /// </summary>
        /// <param name="keyValues">The values of the primary key for the entity to be found.</param>
        /// <returns>False if the entity does not exist in the repository, or true if successfully deleted.</returns>
        public virtual bool Delete(params object[] keyValues)
        {
            var entity = Find(keyValues);
            if (entity == null) return false;
            ApplyDelete(entity);
            return true;
        }

        /// <summary>
        /// Finds an entity with the given primary key values. If no entity is found, then null is returned.
        /// </summary>
        /// <param name="keyValues">The values of the primary key for the entity to be found.</param>
        /// <returns>A task that represents the asynchronous find operation. The task result contains the entity found, or null.</returns>
        public virtual async Task<TEntity> FindAsync(params object[] keyValues)
        {
            return await FindAsync(CancellationToken.None, keyValues);
        }

        /// <summary>
        /// Finds an entity with the given primary key values. If no entity is found, then null is returned.
        /// </summary>
        /// <param name="cancellationToken">A CancellationToken to observe while waiting for the task to complete.</param>
        /// <param name="keyValues">The values of the primary key for the entity to be found.</param>
        /// <returns>A task that represents the asynchronous find operation. The task result contains the entity found, or null.</returns>
        public virtual async Task<TEntity> FindAsync(CancellationToken cancellationToken, params object[] keyValues)
        {
            return await Set.FindAsync(cancellationToken, keyValues);
        }

        /// <summary>
        /// <para>Removes an entity from the respository.</para>
        /// <para>Override to include child entities in delete operation.</para>
        /// </summary>
        /// <param name="keyValues">The values of the primary key for the entity to be found.</param>
        /// <returns>A task that represents the asynchronous delete operation. The task result will be false if the entity does not exist in the repository, or true if successfully removed.</returns>
        public virtual async Task<bool> DeleteAsync(params object[] keyValues)
        {
            return await DeleteAsync(CancellationToken.None, keyValues);
        }

        /// <summary>
        /// <para>Removes an entity from the respository.</para>
        /// <para>Override to include child entities in delete operation.</para>
        /// </summary>
        /// <param name="cancellationToken">A CancellationToken to observe while waiting for the task to complete.</param>
        /// <param name="keyValues">The values of the primary key for the entity to be found.</param>
        /// <returns>A task that represents the asynchronous delete operation. The task result will be false if the entity does not exist in the repository, or true if successfully removed.</returns>
        public virtual async Task<bool> DeleteAsync(CancellationToken cancellationToken, params object[] keyValues)
        {
            var entity = await FindAsync(cancellationToken, keyValues);
            if (entity == null) return false;
            ApplyDelete(entity);
            return true;
        }

        /// <summary>
        /// Load related entities for an object graph.
        /// </summary>
        /// <param name="entity">Entity on which related entities are loaded.</param>
        public virtual void LoadRelatedEntities(TEntity entity)
        {
            Context.LoadRelatedEntities(entity);
        }

        /// <summary>
        /// Load related entities for an object graph.
        /// </summary>
        /// <param name="entity">Entity on which related entities are loaded.</param>
        /// <returns>A task that represents the asynchronous operation</returns>
        public virtual async Task LoadRelatedEntitiesAsync(TEntity entity)
        {
            await Context.LoadRelatedEntitiesAsync(entity);
        }

        /// <summary>
        /// Load related entities for an object graph.
        /// </summary>
        /// <param name="entity">Entity on which related entities are loaded.</param>
        /// <param name="cancellationToken">A CancellationToken to observe while waiting for the task to complete.</param>
        /// <returns>A task that represents the asynchronous operation</returns>
        public virtual async Task LoadRelatedEntitiesAsync(TEntity entity, CancellationToken cancellationToken)
        {
            await Context.LoadRelatedEntitiesAsync(entity, cancellationToken);
        }

        /// <summary>
        /// Load related entities for more than one object graph.
        /// </summary>
        /// <param name="entities">Entities on which related entities are loaded.</param>
        public void LoadRelatedEntities(IEnumerable<TEntity> entities)
        {
            Context.LoadRelatedEntities(entities);
        }

        /// <summary>
        /// Load related entities for more than one object graph.
        /// </summary>
        /// <param name="entities">Entities on which related entities are loaded.</param>
        /// <returns>A task that represents the asynchronous operation</returns>
        public virtual async Task LoadRelatedEntitiesAsync(IEnumerable<TEntity> entities)
        {
            await Context.LoadRelatedEntitiesAsync(entities);
        }

        /// <summary>
        /// Load related entities for more than one object graph.
        /// </summary>
        /// <param name="entities">Entities on which related entities are loaded.</param>
        /// <param name="cancellationToken">A CancellationToken to observe while waiting for the task to complete.</param>
        /// <returns>A task that represents the asynchronous operation</returns>
        public virtual async Task LoadRelatedEntitiesAsync(IEnumerable<TEntity> entities, CancellationToken cancellationToken)
        {
            await Context.LoadRelatedEntitiesAsync(entities, cancellationToken);
        }

        /// <summary>
        /// Mark entity as deleted and apply changes to context.
        /// </summary>
        /// <param name="entity">Entity which is marked as deleted.</param>
        protected void ApplyDelete(TEntity entity)
        {
            entity.TrackingState = TrackingState.Deleted;
            Context.ApplyChanges(entity);
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm.WpfClient/Locators/ViewModelLocator.cs<|end_filename|>
﻿/*
  In App.xaml:
  <Application.Resources>
      <vm:ViewModelLocator xmlns:vm="clr-namespace:WebApiSample.Mvvm.WpfClient"
                                   x:Key="Locator" />
  </Application.Resources>
  
  In the View:
  DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelName}"
*/

using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;

// Toolkit namespace
using SimpleMvvmToolkit;

namespace WebApiSample.Mvvm.WpfClient
{
    /// <summary>
    /// This class creates ViewModels on demand for Views, supplying a
    /// ServiceAgent to the ViewModel if required.
    /// <para>
    /// Place the ViewModelLocator in the App.xaml resources:
    /// </para>
    /// <code>
    /// &lt;Application.Resources&gt;
    ///     &lt;vm:ViewModelLocator xmlns:vm="clr-namespace:WebApiSample.Mvvm.WpfClient"
    ///                                  x:Key="Locator" /&gt;
    /// &lt;/Application.Resources&gt;
    /// </code>
    /// <para>
    /// Then use:
    /// </para>
    /// <code>
    /// DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelName}"
    /// </code>
    /// <para>
    /// Use the <strong>mvvmlocator</strong> or <strong>mvvmlocatornosa</strong>
    /// code snippets to add ViewModels to this locator.
    /// </para>
    /// </summary>
    public class ViewModelLocator
    {
        // Create MainPageViewModel on demand
        public MainPageViewModel MainPageViewModel
        {
            get { return new MainPageViewModel(); }
        }

        // Create CustomerViewModel on demand
        public CustomerOrdersViewModel CustomerOrdersViewModel
        {
            get
            {
                ICustomerServiceAgent customerServiceAgent = new CustomerServiceAgent();
                IOrderServiceAgent orderServiceAgent = new OrderServiceAgent();
                return new CustomerOrdersViewModel(customerServiceAgent, orderServiceAgent);
            }
        }

        // Create OrderViewModelDetail on demand
        public OrderViewModelDetail OrderViewModelDetail
        {
            get
            {
                IProductServiceAgent productServiceAgent = new ProductServiceAgent();
                IOrderServiceAgent orderServiceAgent = new OrderServiceAgent();
                return new OrderViewModelDetail(productServiceAgent, orderServiceAgent);
            }
        }
    }
}

<|start_filename|>Samples/VS2012/WcfSample/WcfSample.Service.Core/CustomerService.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.ServiceModel;
using System.Threading.Tasks;
using TrackableEntities;
using TrackableEntities.Common;
using TrackableEntities.EF6;
using WcfSample.Service.Entities.Contexts;
using WcfSample.Service.Entities.Models;

namespace WcfSample.Service.Core
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class CustomerService : ICustomerService, IDisposable
    {
        private readonly NorthwindSlimContext _dbContext;

        public CustomerService()
        {
            _dbContext = new NorthwindSlimContext();
        }

        public async Task<IEnumerable<Customer>> GetCustomers()
        {
            IEnumerable<Customer> customers = await _dbContext.Customers
                .ToListAsync();
            return customers;
        }

        public async Task<Customer> GetCustomer(string id)
        {
            Customer customer = await _dbContext.Customers
                .SingleOrDefaultAsync(c => c.CustomerId == id);
            return customer;
        }

        public async Task<Customer> CreateCustomer(Customer customer)
        {
            customer.TrackingState = TrackingState.Added;
            _dbContext.ApplyChanges(customer);

            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateException updateEx)
            {
                throw new FaultException(updateEx.Message);
            }

            await _dbContext.LoadRelatedEntitiesAsync(customer);
            customer.AcceptChanges();
            return customer;
        }

        public async Task<Customer> UpdateCustomer(Customer customer)
        {
            _dbContext.ApplyChanges(customer);

            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException updateEx)
            {
                throw new FaultException(updateEx.Message);
            }

            await _dbContext.LoadRelatedEntitiesAsync(customer);
            customer.AcceptChanges();
            return customer;
        }

        public async Task<bool> DeleteCustomer(string id)
        {
            Customer customer = await _dbContext.Customers
                .SingleOrDefaultAsync(c => c.CustomerId == id);
            if (customer == null)
                return false;

            customer.TrackingState = TrackingState.Deleted;
            _dbContext.ApplyChanges(customer);

            try
            {
                await _dbContext.SaveChangesAsync();
                return true;
            }
            catch (DbUpdateConcurrencyException updateEx)
            {
                throw new FaultException(updateEx.Message);
            }
        }

        public void Dispose()
        {
            var dispose = _dbContext as IDisposable;
            if (dispose != null)
            {
                _dbContext.Dispose();
            }
        }
    }
}


<|start_filename|>Source/TrackableEntities.Client/IRefPropertyChangeTrackerResolver.cs<|end_filename|>
﻿using System;

namespace TrackableEntities.Client
{
    /// <summary>
    /// Interface implemented by entities, 1-1 and M-1 properties of which have
    /// non-standard names or locations of the corresponding change trackers.
    /// </summary>
    public interface IRefPropertyChangeTrackerResolver
    {
        /// <summary>
        /// Get change tracker corresponding to a given 1-1 or M-1 property.
        /// <param name="propertyName">Name of 1-1 or M-1 property</param>
        /// </summary>
        ITrackingCollection GetRefPropertyChangeTracker(string propertyName);
    }
}


<|start_filename|>Source/Tests/TrackableEntities.EF.5.Tests/NorthwindModels/Customer.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TrackableEntities.EF.Tests.NorthwindModels
{
    public partial class Customer : ITrackable
    {
        [Key]
        public string CustomerId { get; set; }
        public string CustomerName { get; set; }

        public string TerritoryId { get; set; }
        [ForeignKey("TerritoryId")]
        public Territory Territory { get; set; }

        public List<Order> Orders { get; set; }
        public CustomerSetting CustomerSetting { get; set; }
        public List<CustomerAddress> CustomerAddresses { get; set; }

        [NotMapped]
        public TrackingState TrackingState { get; set; }
        [NotMapped]
        public ICollection<string> ModifiedProperties { get; set; }
    }
}


<|start_filename|>Source/Tests/TrackableEntities.Client.Tests.Entities/NorthwindModels/OrderDetail.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace TrackableEntities.Client.Tests.Entities.NorthwindModels
{
    [JsonObject(IsReference = true)]
    public class OrderDetail : EntityBase
    {
        private int _productId;
        public int ProductId
        {
            get { return _productId; }
            set
            {
                if (value == _productId) return;
                _productId = value;
                NotifyPropertyChanged(() => ProductId);
            }
        }

        private int _orderId;
        public int OrderId
        {
            get { return _orderId; }
            set
            {
                if (value == _orderId) return;
                _orderId = value;
                NotifyPropertyChanged(() => OrderId);
            }
        }

        private Product _product;
        public Product Product
        {
            get { return _product; }
            set
            {
                if (value == _product) return;
                _product = value;
                ProductChangeTracker = _product == null ? null
                    : new ChangeTrackingCollection<Product> { _product };
                NotifyPropertyChanged(() => Product);
            }
        }
        private ChangeTrackingCollection<Product> ProductChangeTracker { get; set; }

        public Order Order
        {
            get { return _order; }
            set
            {
                if (Equals(value, _order)) return;
                _order = value;
                OrderChangeTracker = _order == null ? null
                    : new ChangeTrackingCollection<Order> { _order };
                NotifyPropertyChanged(() => Order);
            }
        }
        private Order _order;
        private ChangeTrackingCollection<Order> OrderChangeTracker { get; set; }

        private decimal _unitPrice;
        public decimal UnitPrice
        {
            get { return _unitPrice; }
            set
            {
                if (value == _unitPrice) return;
                _unitPrice = value;
                NotifyPropertyChanged(() => UnitPrice);
            }
        }

        private double _quanity;
        public double Quantity
        {
            get { return _quanity; }
            set
            {
                if (Math.Abs(value - _quanity) < double.Epsilon) return;
                _quanity = value;
                NotifyPropertyChanged(() => Quantity);
            }
        }
    }
}


<|start_filename|>Extensions/Common/Wizards/EntitiesSelectionWizard/EntitiesSelectionDialog.cs<|end_filename|>
﻿using System;
using System.Windows.Forms;

namespace EntitiesSelectionWizard
{
    public partial class EntitiesSelectionDialog : Form
    {
        private readonly bool _multiproject;
        private readonly bool _webApiSharedPortable;
        private readonly ListViewItem _portableListViewItemItem;
        private PageSelection _pageIndex = PageSelection.FirstPage;

        public EntitiesSelectionDialog(bool multiproject = false, 
            bool webApiSharedPortable = false)
        {
            Application.EnableVisualStyles();
            InitializeComponent();

            _multiproject = multiproject;
            _webApiSharedPortable = webApiSharedPortable;
            _portableListViewItemItem = portableDotNetListView.Items[1];

            if (_multiproject)
            {
                clientServiceListView.Visible = true;
                serviceClientSharedListView.Visible = false;
            }
            else
            {
                clientServiceListView.Visible = false;
                serviceClientSharedListView.Visible = true;
            }

            clientServiceListView.Items[0].Selected = true;
            serviceClientSharedListView.Items[0].Selected = true;
            portableDotNetListView.Items[0].Selected = true;
        }

        public EntitiesSelection EntitiesSelection { get; set; }

        private void SetPageState()
        {
            if (_pageIndex == PageSelection.FirstPage)
            {
                if (_multiproject)
                    clientServiceListView.Visible = true;
                else
                    serviceClientSharedListView.Visible = true;
                portableDotNetListView.Visible = false;

                previousButton.Enabled = false;
                if (_multiproject)
                {
                    nextButton.Enabled = true;
                    finishButton.Enabled = false;
                    AcceptButton = nextButton;
                }
                else
                {
                    ListView entitiesTypeListView;
                    if (_multiproject) entitiesTypeListView = clientServiceListView;
                    else entitiesTypeListView = serviceClientSharedListView;
                    EntitiesTypeSelection selection = GetEntitiesTypeSelection(entitiesTypeListView);
                    if (selection == EntitiesTypeSelection.ServiceEntities)
                    {
                        nextButton.Enabled = false;
                        finishButton.Enabled = true;
                        AcceptButton = finishButton;
                    }
                    else
                    {
                        nextButton.Enabled = true;
                        finishButton.Enabled = false;
                        AcceptButton = nextButton;
                    }
                }
            }
            else
            {
                clientServiceListView.Visible = false;
                serviceClientSharedListView.Visible = false;
                portableDotNetListView.Visible = true;

                previousButton.Enabled = true;
                nextButton.Enabled = false;
                finishButton.Enabled = true;
                AcceptButton = finishButton;
            }
        }

        private EntitiesTypeSelection GetEntitiesTypeSelection(ListView entitiesTypeListView)
        {
            int selection = 0;
            if (entitiesTypeListView.SelectedIndices.Count > 0)
                selection = entitiesTypeListView.SelectedIndices[0];
            if (ReferenceEquals(entitiesTypeListView, clientServiceListView))
            {
                switch (selection)
                {
                    case 0:
                        return EntitiesTypeSelection.ClientServiceEntities;
                    default:
                        return EntitiesTypeSelection.SharedEntities;
                }
            }
            if (ReferenceEquals(entitiesTypeListView, serviceClientSharedListView))
            {
                switch (selection)
                {
                    case 0:
                        return EntitiesTypeSelection.ServiceEntities;
                    case 1:
                        return EntitiesTypeSelection.ClientEntities;
                    default:
                        return EntitiesTypeSelection.SharedEntities;
                }
            }
            throw new InvalidOperationException("Unsupported entities type selection.");
        }

        private EntitiesCategorySelection GetEntitiesCategorySelection(ListView entitiesCategoryListView)
        {
            int selection = 0;
            if (entitiesCategoryListView.SelectedIndices.Count > 0)
                selection = entitiesCategoryListView.SelectedIndices[0];
            if (ReferenceEquals(entitiesCategoryListView, portableDotNetListView))
            {
                switch (selection)
                {
                    case 0:
                        return EntitiesCategorySelection.DotNetEntities;
                    default:
                        return EntitiesCategorySelection.PortableEntities;
                }
            }
            throw new InvalidOperationException("Unsupported entities category selection.");
        }

        private string GetSelectedEntityType()
        {
            EntitiesTypeSelection selection;
            if (_multiproject)
            {
                selection = GetEntitiesTypeSelection(clientServiceListView);
                switch (selection)
                {
                    case EntitiesTypeSelection.ClientServiceEntities:
                        return "Separate Client / Service";
                    case EntitiesTypeSelection.SharedEntities:
                        return "Shared";
                }
            }
            else
            {
                selection = GetEntitiesTypeSelection(serviceClientSharedListView);
                switch (selection)
                {
                    case EntitiesTypeSelection.ClientEntities:
                        return "Client";
                    case EntitiesTypeSelection.ServiceEntities:
                        return "Service";
                    case EntitiesTypeSelection.SharedEntities:
                        return "Shared";
                }
            }
            return string.Empty;
        }

        private void clientServiceListView_SelectedIndexChanged(object sender, EventArgs e)
        {
            EntitiesTypeSelection selection = GetEntitiesTypeSelection(clientServiceListView);
            switch (selection)
            {
                case EntitiesTypeSelection.ClientServiceEntities:
                    descriptionLabel.Text = Constants.Descriptions.ClientServiceEntities;
                    break;
                case EntitiesTypeSelection.SharedEntities:
                    descriptionLabel.Text = Constants.Descriptions.SharedEntities;
                    break;
            }
            SetPageState();
        }

        private void serviceClientSharedListView_SelectedIndexChanged(object sender, EventArgs e)
        {
            EntitiesTypeSelection selection = GetEntitiesTypeSelection(serviceClientSharedListView);
            switch (selection)
            {
                case EntitiesTypeSelection.ClientEntities:
                    descriptionLabel.Text = Constants.Descriptions.ClientEntities;
                    break;
                case EntitiesTypeSelection.ServiceEntities:
                    descriptionLabel.Text = Constants.Descriptions.ServiceEntities;
                    break;
                case EntitiesTypeSelection.SharedEntities:
                    descriptionLabel.Text = Constants.Descriptions.SharedEntities;
                    break;
            }
            SetPageState();
        }

        private void portableDotNetListView_SelectedIndexChanged(object sender, EventArgs e)
        {
            string entityType = GetSelectedEntityType();
            EntitiesCategorySelection selection = GetEntitiesCategorySelection(portableDotNetListView);
            switch (selection)
            {
                case EntitiesCategorySelection.PortableEntities:
                    descriptionLabel.Text = string.Format(Constants.Descriptions.PortableEntities, entityType);
                    break;
                case EntitiesCategorySelection.DotNetEntities:
                    descriptionLabel.Text = string.Format(Constants.Descriptions.DotNetEntities, entityType);
                    break;
            }
            SetPageState();
        }

        private EntitiesSelection ToSelectionType(EntitiesTypeSelection typeSelection)
        {
            switch (typeSelection)
            {
                case EntitiesTypeSelection.ClientServiceEntities:
                    return EntitiesSelection.ClientService;
                case EntitiesTypeSelection.ServiceEntities:
                    return EntitiesSelection.Service;
                case EntitiesTypeSelection.ClientEntities:
                    return EntitiesSelection.Client;
                case EntitiesTypeSelection.SharedEntities:
                    return EntitiesSelection.Shared;
                default:
                    return EntitiesSelection.None;
            }
        }

        private EntitiesSelection ToSelectionType(EntitiesCategorySelection categorySelection)
        {
            switch (categorySelection)
            {
                case EntitiesCategorySelection.PortableEntities:
                    return EntitiesSelection.Portable;
                case EntitiesCategorySelection.DotNetEntities:
                    return EntitiesSelection.DotNet45;
                default:
                    return EntitiesSelection.None;
            }
        }

        private void previousButton_Click(object sender, EventArgs e)
        {
            _pageIndex = PageSelection.FirstPage;
            SetPageState();
            if (_multiproject)
            {
                clientServiceListView.Focus();
                clientServiceListView_SelectedIndexChanged(this, EventArgs.Empty);
            }
            else
            {
                serviceClientSharedListView.Focus();
                serviceClientSharedListView_SelectedIndexChanged(this, EventArgs.Empty);
            }
        }

        private void nextButton_Click(object sender, EventArgs e)
        {
            _pageIndex = PageSelection.SecondPage;
            if (_webApiSharedPortable)
            {
                EntitiesTypeSelection selection = GetEntitiesTypeSelection(clientServiceListView);
                switch (selection)
                {
                    case EntitiesTypeSelection.ClientServiceEntities:
                        if (!portableDotNetListView.Items.Contains(_portableListViewItemItem))
                        {
                            portableDotNetListView.Items.Insert(1, _portableListViewItemItem);
                            portableDotNetListView.Items[1].EnsureVisible();
                            portableDotNetListView.Items[0].Focused = true;
                            portableDotNetListView.Items[0].Selected = true;
                        }
                        break;
                    case EntitiesTypeSelection.SharedEntities:
                        if (portableDotNetListView.Items.Contains(_portableListViewItemItem))
                        {
                            portableDotNetListView.Items.Remove(_portableListViewItemItem);
                            portableDotNetListView.Items[0].Focused = true;
                            portableDotNetListView.Items[0].Selected = true;
                        }
                        break;
                }
            }
            SetPageState();
            portableDotNetListView.Focus();
            portableDotNetListView_SelectedIndexChanged(this, EventArgs.Empty);
        }

        private void cancelButton_Click(object sender, EventArgs e)
        {
            EntitiesSelection = EntitiesSelection.None;
            DialogResult = DialogResult.Cancel;
        }

        private void finishButton_Click(object sender, EventArgs e)
        {
            EntitiesTypeSelection typeSelection;
            if (_multiproject)
                typeSelection = GetEntitiesTypeSelection(clientServiceListView);
            else
                typeSelection = GetEntitiesTypeSelection(serviceClientSharedListView);
            EntitiesCategorySelection categorySelection = EntitiesCategorySelection.DotNetEntities;

            if (typeSelection != EntitiesTypeSelection.ServiceEntities)
                categorySelection = GetEntitiesCategorySelection(portableDotNetListView);

            EntitiesSelection entitiesType = ToSelectionType(typeSelection);
            EntitiesSelection entitiesCategory = ToSelectionType(categorySelection);
            EntitiesSelection = entitiesType | entitiesCategory;
            DialogResult = DialogResult.OK;
        }

        private enum PageSelection
        {
            FirstPage = 0,
            SecondPage = 1
        }

        private enum EntitiesTypeSelection
        {
            ServiceEntities = 0,
            ClientEntities = 1,
            ClientServiceEntities = 2,
            SharedEntities = 3
        }

        private enum EntitiesCategorySelection
        {
            PortableEntities = 0,
            DotNetEntities = 1
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Patterns/WebApiSample.Service.EF/UnitsOfWork/NorthwindUnitOfWork.cs<|end_filename|>
﻿using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Threading;
using System.Threading.Tasks;
using TrackableEntities.Patterns.EF6;
using WebApiSample.Service.EF.Contexts;
using WebApiSample.Service.Persistence.Exceptions;
using WebApiSample.Service.Persistence.Repositories;
using WebApiSample.Service.Persistence.UnitsOfWork;

namespace WebApiSample.Service.EF.UnitsOfWork
{
    public class NorthwindUnitOfWork : UnitOfWork, INorthwindUnitOfWork
    {
        private readonly ICustomerRepository _customerRepository;
        private readonly IOrderRepository _orderRepository;

        public NorthwindUnitOfWork(INorthwindSlimContext context,
            ICustomerRepository customerRepository,
            IOrderRepository orderRepository) :
            base(context as DbContext)
        {
            _customerRepository = customerRepository;
            _orderRepository = orderRepository;
        }

        public ICustomerRepository CustomerRepository
        {
            get { return _customerRepository; }
        }

        public IOrderRepository OrderRepository
        {
            get { return _orderRepository; }
        }

        public override int SaveChanges()
        {
            try
            {
                return base.SaveChanges();
            }
            catch (DbUpdateConcurrencyException concurrencyException)
            {
                throw new UpdateConcurrencyException(concurrencyException.Message,
                    concurrencyException);
            }
            catch (DbUpdateException updateException)
            {
                throw new UpdateException(updateException.Message,
                    updateException);
            }
        }

        public override Task<int> SaveChangesAsync()
        {
            return SaveChangesAsync(CancellationToken.None);
        }

        public override Task<int> SaveChangesAsync(CancellationToken cancellationToken)
        {
            try
            {
                return base.SaveChangesAsync(cancellationToken);
            }
            catch (DbUpdateConcurrencyException concurrencyException)
            {
                throw new UpdateConcurrencyException(concurrencyException.Message,
                    concurrencyException);
            }
            catch (DbUpdateException updateException)
            {
                throw new UpdateException(updateException.Message, 
                    updateException);
            }
        }
    }
}


<|start_filename|>Extensions/Common/Wizards/TrackableEntities.ItemWizard/WizardHelper.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using EnvDTE;
using EnvDTE80;
using ItemTemplateParametersWizard;
using Microsoft.VisualStudio.TemplateWizard;

namespace TrackableEntities.ItemWizard
{
    internal static class WizardHelper
    {
        public static void AddCustomParameters(object automationObject,
            Dictionary<string, string> replacementsDictionary, 
            string dialogTitle, string dialogMessage, bool getDbContextName, int dialogWidth)
        {
            // Get referenced types
            var dte2 = (DTE2)automationObject;
            List<ModelTypeInfo> modelTypes = GetReferencedTypes(dte2).ToList();
            const string noEntitiesMessage = "Referenced projects do not contain any {0}." +
                    "\r\nAdd service entities by reverse engineering Code First classes from an existing database, then re-build the solution.";

            // Check for trackable entities in referenced projects
            if (modelTypes.Count(t => t.ModelType == ModelType.Trackable) == 0)
            {
                MessageBox.Show(string.Format(noEntitiesMessage, "Trackable model classes"),
                    "Trackable Entities Not Found");
                throw new WizardBackoutException();
            }

            // Check for DbContext types in referenced projects
            if (getDbContextName && modelTypes.Count(t => t.ModelType == ModelType.DbContext) == 0)
            {
                MessageBox.Show(string.Format(noEntitiesMessage, "DbContext classes"),
                    "DbContext Class Not Found");
                throw new WizardBackoutException();
            }

            // Prompt user for Entity and DbContext names
            Form dialog;
            if (getDbContextName)
                dialog = new ModelTypesContextDialog(modelTypes, dialogTitle, dialogMessage, dialogWidth); 
            else
                dialog = new ModelTypesDialog(modelTypes, dialogTitle, dialogMessage, dialogWidth);
            if (dialog.ShowDialog() == DialogResult.Cancel)
                throw new WizardBackoutException();

            var modelTypesDialog = ((IModelTypes) dialog);
            string entityName = modelTypesDialog.ModelTypesDialogInfo.EntityName;
            string entitySetName = modelTypesDialog.ModelTypesDialogInfo.EntitySetName;
            string dbContextName = modelTypesDialog.ModelTypesDialogInfo.DbContextName;
            string baseNamespace = modelTypesDialog.ModelTypesDialogInfo.BaseNamespace;
            string entitiesNamespace = modelTypesDialog.ModelTypesDialogInfo.EntitiesNamespace;

            replacementsDictionary.Add("$entityName$", entityName);
            replacementsDictionary.Add("$entitySetName$", entitySetName);
            replacementsDictionary.Add("$dbContextName$", dbContextName);
            replacementsDictionary.Add("$baseNamespace$", baseNamespace);
            replacementsDictionary.Add("$entitiesNamespace$", entitiesNamespace);
        }

        private static IEnumerable<ModelTypeInfo> GetReferencedTypes(DTE2 dte2)
        {
            Project activeProject = dte2.ActiveSolutionProjects[0];
            var project = activeProject.Object as VSLangProj.VSProject;
            if (project != null)
            {
                foreach (VSLangProj.Reference reference in project.References)
                {
                    if (reference.SourceProject != null)
                    {
                        if (!File.Exists(reference.Path))
                        {
                            continue;
                        }

                        // Get type info from assembly
                        List<ModelTypeInfo> modelTypes = ModelReflectionHelper.GetModelTypes
                            (new FileInfo(reference.Path));
                        foreach (var modelType in modelTypes)
                        {
                            yield return modelType;
                        }
                    }
                }
            }
        }

        private static string CopyFileToTemp(string sourcePath, ref string destDir)
        {
            if (!File.Exists(sourcePath)) return null;
            string destFileName = Path.GetFileName(sourcePath);
            if (string.IsNullOrWhiteSpace(destDir))
                destDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
            string destPath = Path.Combine(destDir, destFileName);
            Directory.CreateDirectory(destDir);
            File.Copy(sourcePath, destPath);
            return destPath;
        }

        private static void DeleteFilesFromTemp(string destDir)
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(destDir) && Directory.Exists(destDir))
                {
                    Directory.Delete(destDir);
                }
            }
            catch (Exception) { } // Just go on if there's an error
        }
    }
}


<|start_filename|>Samples/VS2012/WebApiSample/WebApiSample.Service.Entities/Models/Territory.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using TrackableEntities;

namespace WebApiSample.Service.Entities.Models
{
    [JsonObject(IsReference = true)]
    [DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
    public partial class Territory : ITrackable
    {
        public Territory()
        {
            this.Employees = new List<Employee>();
        }

        [DataMember]
        public string TerritoryId { get; set; }
        [DataMember]
        public string TerritoryDescription { get; set; }
        [DataMember]
        public List<Employee> Employees { get; set; }

        [DataMember]
        public TrackingState TrackingState { get; set; }
        [DataMember]
        public ICollection<string> ModifiedProperties { get; set; }
        [JsonProperty, DataMember]
        private Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/Contexts/NorthwindTestDbContext.cs<|end_filename|>
﻿using System;
using System.Data.Entity;
using TrackableEntities.EF.Tests;
using TrackableEntities.EF.Tests.NorthwindModels;

namespace TrackableEntities.Tests.Acceptance.Contexts
{
    public class NorthwindTestDbContext : DbContext
    {
        private const string TestDbName = "NorthwindAcceptTestDb";

        public NorthwindTestDbContext(CreateDbOptions createDbOptions = CreateDbOptions.CreateDatabaseIfNotExists)
            : base(TestDbName)
        {
            switch (createDbOptions)
            {
                case CreateDbOptions.DropCreateDatabaseAlways:
                    Database.SetInitializer(new DropCreateDatabaseAlways<NorthwindTestDbContext>());
                    break;
                case CreateDbOptions.DropCreateDatabaseSeed:
                    Database.SetInitializer(new NorthwindDbInitializer());
                    break;
                case CreateDbOptions.DropCreateDatabaseIfModelChanges:
                    Database.SetInitializer(new DropCreateDatabaseIfModelChanges<NorthwindTestDbContext>());
                    break;
                default:
                    Database.SetInitializer(new DropCreateDatabaseAlways<NorthwindTestDbContext>());
                    break;
            }
        }

        public DbSet<Category> Categories { get; set; }
        public DbSet<Product> Products { get; set; }
        public DbSet<Customer> Customers { get; set; }
        public DbSet<CustomerSetting> CustomerSettings { get; set; }
        public DbSet<Order> Orders { get; set; }
        public DbSet<OrderDetail> OrderDetails { get; set; }
        public DbSet<Employee> Employees { get; set; }
        public DbSet<Territory> Territories { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<CustomerSetting>()
                .HasRequired(x => x.Customer)
                .WithOptional(x => x.CustomerSetting);
        }
    }
}


<|start_filename|>Extensions/Common/Wizards/ItemTemplateParametersWizard/ModelType.cs<|end_filename|>
﻿using System;

namespace ItemTemplateParametersWizard
{
    public enum ModelType
    {
        Other,
        Trackable,
        DbContext,
    }
}


<|start_filename|>Extensions/Common/Wizards/ItemTemplateParametersWizard/ModelTypesContextDialog.Designer.cs<|end_filename|>
﻿using System.Windows.Forms;

namespace ItemTemplateParametersWizard
{
    public partial class ModelTypesContextDialog : Form
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.descriptionLabel = new System.Windows.Forms.Label();
            this.label4 = new System.Windows.Forms.Label();
            this.label3 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.cancelButton = new System.Windows.Forms.Button();
            this.okButton = new System.Windows.Forms.Button();
            this.entitySetTextBox = new System.Windows.Forms.TextBox();
            this.entityNameComboBox = new System.Windows.Forms.ComboBox();
            this.dbContextComboBox = new System.Windows.Forms.ComboBox();
            this.buttonsPanel = new System.Windows.Forms.Panel();
            this.buttonsPanel.SuspendLayout();
            this.SuspendLayout();
            // 
            // descriptionLabel
            // 
            this.descriptionLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.descriptionLabel.Font = new System.Drawing.Font("Arial", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.descriptionLabel.Location = new System.Drawing.Point(62, 22);
            this.descriptionLabel.Name = "descriptionLabel";
            this.descriptionLabel.Size = new System.Drawing.Size(509, 44);
            this.descriptionLabel.TabIndex = 1;
            this.descriptionLabel.Text = "Description";
            this.descriptionLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.Location = new System.Drawing.Point(33, 121);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(86, 13);
            this.label4.TabIndex = 15;
            this.label4.Text = "Entity Set Name:";
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(33, 151);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(91, 13);
            this.label3.TabIndex = 14;
            this.label3.Text = "DbContext Name:";
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(33, 91);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(67, 13);
            this.label2.TabIndex = 13;
            this.label2.Text = "Entity Name:";
            // 
            // cancelButton
            // 
            this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
            this.cancelButton.Location = new System.Drawing.Point(108, 10);
            this.cancelButton.Name = "cancelButton";
            this.cancelButton.Size = new System.Drawing.Size(75, 23);
            this.cancelButton.TabIndex = 17;
            this.cancelButton.TabStop = false;
            this.cancelButton.Text = "Cancel";
            this.cancelButton.UseVisualStyleBackColor = true;
            this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
            // 
            // okButton
            // 
            this.okButton.Location = new System.Drawing.Point(16, 10);
            this.okButton.Name = "okButton";
            this.okButton.Size = new System.Drawing.Size(75, 23);
            this.okButton.TabIndex = 16;
            this.okButton.TabStop = false;
            this.okButton.Text = "OK";
            this.okButton.UseVisualStyleBackColor = true;
            this.okButton.Click += new System.EventHandler(this.okButton_Click);
            // 
            // entitySetTextBox
            // 
            this.entitySetTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.entitySetTextBox.Location = new System.Drawing.Point(136, 118);
            this.entitySetTextBox.Name = "entitySetTextBox";
            this.entitySetTextBox.Size = new System.Drawing.Size(459, 20);
            this.entitySetTextBox.TabIndex = 1;
            // 
            // entityNameComboBox
            // 
            this.entityNameComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.entityNameComboBox.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Append;
            this.entityNameComboBox.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems;
            this.entityNameComboBox.DisplayMember = "DisplayName";
            this.entityNameComboBox.FormattingEnabled = true;
            this.entityNameComboBox.Location = new System.Drawing.Point(136, 88);
            this.entityNameComboBox.Name = "entityNameComboBox";
            this.entityNameComboBox.Size = new System.Drawing.Size(459, 21);
            this.entityNameComboBox.TabIndex = 0;
            // 
            // dbContextComboBox
            // 
            this.dbContextComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.dbContextComboBox.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Append;
            this.dbContextComboBox.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems;
            this.dbContextComboBox.DisplayMember = "DisplayName";
            this.dbContextComboBox.FormattingEnabled = true;
            this.dbContextComboBox.Location = new System.Drawing.Point(136, 148);
            this.dbContextComboBox.Name = "dbContextComboBox";
            this.dbContextComboBox.Size = new System.Drawing.Size(459, 21);
            this.dbContextComboBox.TabIndex = 2;
            // 
            // buttonsPanel
            // 
            this.buttonsPanel.Controls.Add(this.okButton);
            this.buttonsPanel.Controls.Add(this.cancelButton);
            this.buttonsPanel.Location = new System.Drawing.Point(219, 175);
            this.buttonsPanel.Name = "buttonsPanel";
            this.buttonsPanel.Size = new System.Drawing.Size(201, 41);
            this.buttonsPanel.TabIndex = 18;
            // 
            // ModelTypesContextDialog
            // 
            this.AcceptButton = this.okButton;
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.CancelButton = this.cancelButton;
            this.ClientSize = new System.Drawing.Size(634, 225);
            this.Controls.Add(this.buttonsPanel);
            this.Controls.Add(this.dbContextComboBox);
            this.Controls.Add(this.entityNameComboBox);
            this.Controls.Add(this.entitySetTextBox);
            this.Controls.Add(this.label4);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.descriptionLabel);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "ModelTypesContextDialog";
            this.ShowInTaskbar = false;
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "Model Types";
            this.Load += new System.EventHandler(this.ModelTypesDialog_Load);
            this.Resize += new System.EventHandler(this.ModelTypesContextDialog_Resize);
            this.buttonsPanel.ResumeLayout(false);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Label descriptionLabel;
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.Button cancelButton;
        private System.Windows.Forms.Button okButton;
        private System.Windows.Forms.TextBox entitySetTextBox;
        private System.Windows.Forms.ComboBox entityNameComboBox;
        private System.Windows.Forms.ComboBox dbContextComboBox;
        private Panel buttonsPanel;
    }
}

<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm/WebApiSample.Mvvm.Service.Entities/Contexts/NorthwindSlimContext.cs<|end_filename|>
using System.Data.Entity;
using WebApiSample.Mvvm.Service.Entities.Models;
using WebApiSample.Mvvm.Service.Entities.Models.Mapping;

namespace WebApiSample.Mvvm.Service.Entities.Contexts
{
    public partial class NorthwindSlimContext : DbContext
    {
        static NorthwindSlimContext()
        {
            Database.SetInitializer(new NullDatabaseInitializer<NorthwindSlimContext>());
        }

        public NorthwindSlimContext()
            : base("Name=NorthwindSlimContext")
        {
            this.Configuration.LazyLoadingEnabled = false;
            this.Configuration.ProxyCreationEnabled = false;
        }

        public DbSet<Category> Categories { get; set; }
        public DbSet<Customer> Customers { get; set; }
        public DbSet<CustomerSetting> CustomerSettings { get; set; }
        public DbSet<Employee> Employees { get; set; }
        public DbSet<Order> Orders { get; set; }
        public DbSet<OrderDetail> OrderDetails { get; set; }
        public DbSet<Product> Products { get; set; }
        public DbSet<Territory> Territories { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new CategoryMap());
            modelBuilder.Configurations.Add(new CustomerMap());
            modelBuilder.Configurations.Add(new CustomerSettingMap());
            modelBuilder.Configurations.Add(new EmployeeMap());
            modelBuilder.Configurations.Add(new OrderMap());
            modelBuilder.Configurations.Add(new OrderDetailMap());
            modelBuilder.Configurations.Add(new ProductMap());
            modelBuilder.Configurations.Add(new TerritoryMap());
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample/WebApiSample.Client.Entities.Net45/Models/Employee.cs<|end_filename|>
using System;
using TrackableEntities.Client;

namespace WebApiSample.Client.Entities.Models
{
    public partial class Employee : EntityBase
    {
        public Employee()
        {
            Territories = new ChangeTrackingCollection<Territory>();
        }

		public int EmployeeId
		{ 
			get { return _EmployeeId; }
			set
			{
				if (Equals(value, _EmployeeId)) return;
				_EmployeeId = value;
				NotifyPropertyChanged();
			}
		}
		private int _EmployeeId;

		public string LastName
		{ 
			get { return _LastName; }
			set
			{
				if (Equals(value, _LastName)) return;
				_LastName = value;
				NotifyPropertyChanged();
			}
		}
		private string _LastName;

		public string FirstName
		{ 
			get { return _FirstName; }
			set
			{
				if (Equals(value, _FirstName)) return;
				_FirstName = value;
				NotifyPropertyChanged();
			}
		}
		private string _FirstName;

		public DateTime? BirthDate
		{ 
			get { return _BirthDate; }
			set
			{
				if (Equals(value, _BirthDate)) return;
				_BirthDate = value;
				NotifyPropertyChanged();
			}
		}
		private DateTime? _BirthDate;

		public DateTime? HireDate
		{ 
			get { return _HireDate; }
			set
			{
				if (Equals(value, _HireDate)) return;
				_HireDate = value;
				NotifyPropertyChanged();
			}
		}
		private DateTime? _HireDate;

		public string City
		{ 
			get { return _City; }
			set
			{
				if (Equals(value, _City)) return;
				_City = value;
				NotifyPropertyChanged();
			}
		}
		private string _City;

		public string Country
		{ 
			get { return _Country; }
			set
			{
				if (Equals(value, _Country)) return;
				_Country = value;
				NotifyPropertyChanged();
			}
		}
		private string _Country;

		public ChangeTrackingCollection<Territory> Territories
		{
			get { return _Territories; }
			set
			{
				if (Equals(value, _Territories)) return;
				_Territories = value;
				NotifyPropertyChanged();
			}
		}
		private ChangeTrackingCollection<Territory> _Territories;
    }
}


<|start_filename|>Samples/VS2013/WebApiSample/WebApiSample.Service.Entities/Contexts/NorthwindSlim.Mappings.cs<|end_filename|>
﻿using System;
using System.Data.Entity;
using WebApiSample.Service.Entities.Models;

namespace WebApiSample.Service.Entities.Contexts
{
    public partial class NorthwindSlim
    {
        partial void ModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<CustomerSetting>()
                .HasKey(e => e.CustomerId);
        }
    }
}


<|start_filename|>Samples/VS2012/WcfSample/WcfSample.Service.Entities/Models/OrderDetail.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using TrackableEntities;

namespace WcfSample.Service.Entities.Models
{
    [JsonObject(IsReference = true)]
    [DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
    public partial class OrderDetail : ITrackable
    {
        [DataMember]
        public int OrderDetailId { get; set; }
        [DataMember]
        public int OrderId { get; set; }
        [DataMember]
        public int ProductId { get; set; }
        [DataMember]
        public decimal UnitPrice { get; set; }
        [DataMember]
        public short Quantity { get; set; }
        [DataMember]
        public float Discount { get; set; }
        [DataMember]
        public Order Order { get; set; }
        [DataMember]
        public Product Product { get; set; }

        [DataMember]
        public TrackingState TrackingState { get; set; }
        [DataMember]
        public ICollection<string> ModifiedProperties { get; set; }
        [JsonProperty, DataMember]
        private Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/WebHost/Constants.cs<|end_filename|>
﻿using System;

namespace TrackableEntities.Tests.Acceptance.WebHost
{
    public static class Constants
    {
        public static class WebHost
        {
            public const string HostName = "localhost";
        }
    }
}


<|start_filename|>Source/TrackableEntities.Common/TrackableExtensions.cs<|end_filename|>
﻿using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

namespace TrackableEntities.Common
{
    /// <summary>
    /// Extension methods for entities that implement ITrackable.
    /// </summary>
    public static class TrackableExtensions
    {
        /// <summary>
        /// Set tracking state to Unchanged on an entity and its child collections.
        /// </summary>
        /// <param name="item">Trackable object</param>
        public static void AcceptChanges(this ITrackable item)
        {
            // Recursively set tracking state for child collections
            item.AcceptChanges(null);
        }

        /// <summary>
        /// Set tracking state to Unchanged on entities and their child collections.
        /// </summary>
        /// <param name="items">Trackable objects</param>
        public static void AcceptChanges(this IEnumerable<ITrackable> items)
        {
            // Recursively set tracking state for child collections
            foreach (var item in items)
                item.AcceptChanges(null);
        }

        private static void AcceptChanges(this ITrackable item, ObjectVisitationHelper visitationHelper)
        {
            ObjectVisitationHelper.EnsureCreated(ref visitationHelper);

            // Prevent endless recursion
            if (!visitationHelper.TryVisit(item)) return;

            // Set tracking state for child collections
            foreach (var navProp in item.GetNavigationProperties())
            {
                // Apply changes to 1-1 and M-1 properties
                foreach (var refProp in navProp.AsReferenceProperty())
                    refProp.EntityReference.AcceptChanges(visitationHelper);

                // Apply changes to 1-M properties
                foreach (var colProp in navProp.AsCollectionProperty<IList>())
                {
                    var items = colProp.EntityCollection;
                    var count = items.Count;
                    for (int i = count - 1; i > -1; i--)
                    {
                        // Stop recursion if trackable hasn't been visited
                        var trackable = items[i] as ITrackable;
                        if (trackable != null)
                        {
                            if (trackable.TrackingState == TrackingState.Deleted)
                                // Remove items marked as deleted
                                items.RemoveAt(i);
                            else
                                // Recursively accept changes on trackable
                                trackable.AcceptChanges(visitationHelper);
                        }
                    }
                }
            }

            // Set tracking state and clear modified properties
            item.TrackingState = TrackingState.Unchanged;
            item.ModifiedProperties = null;
        }

        /// <summary>
        /// Get a list of all navigation properties (entity references and entity collections)
        /// of a given entity.
        /// </summary>
        /// <param name="entity">Entity object</param>
        /// <param name="skipNulls">Null properties are skipped</param>
        public static IEnumerable<EntityNavigationProperty>
            GetNavigationProperties(this ITrackable entity, bool skipNulls = true)
        {
            INavigationPropertyInspector inspector = entity as INavigationPropertyInspector;
            if (inspector == null)
                inspector = new DefaultNavigationPropertyInspector(entity);

            foreach (var navProp in inspector.GetNavigationProperties())
            {
                // 1-1 and M-1 properties
                foreach (var refProp in navProp.AsReferenceProperty())
                {
                    if (skipNulls && refProp.EntityReference == null) continue; // skip nulls
                    yield return refProp;
                }

                // 1-M and M-M properties
                foreach (var colProp in navProp.AsCollectionProperty())
                {
                    if (skipNulls && colProp.EntityCollection == null) continue; // skip nulls
                    yield return colProp;
                }
            }
        }

        /// <summary>
        /// Get an entity collection property (1-M or M-M) for the given entity.
        /// </summary>
        /// <typeparam name="TEntityCollection">Type of entity collection</typeparam>
        /// <param name="entity">Entity object</param>
        /// <param name="property">Property information</param>
        public static EntityCollectionProperty<TEntityCollection>
            GetEntityCollectionProperty<TEntityCollection>(this ITrackable entity,
                PropertyInfo property)
            where TEntityCollection : class
        {
            return entity.GetNavigationProperties(false)
                .Where(np => np.Property == property)
                .OfCollectionType<TEntityCollection>()
                .Single();
        }

        /// <summary>
        /// Get an entity collection property (1-M or M-M) for the given entity.
        /// </summary>
        /// <param name="entity">Entity object</param>
        /// <param name="property">Property information</param>
        public static EntityCollectionProperty<IEnumerable<ITrackable>>
            GetEntityCollectionProperty(this ITrackable entity, PropertyInfo property)
        {
            return entity.GetEntityCollectionProperty<IEnumerable<ITrackable>>(property);
        }

        /// <summary>
        /// Get an entity reference property (1-1 or M-1) for the given entity.
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="entity">Entity object</param>
        /// <param name="property">Property information</param>
        public static EntityReferenceProperty<TEntity>
            GetEntityReferenceProperty<TEntity>(this ITrackable entity, PropertyInfo property)
            where TEntity : class, ITrackable
        {
            return entity.GetNavigationProperties(false)
                .Where(np => np.Property == property)
                .OfReferenceType<TEntity>()
                .Single();
        }

        /// <summary>
        /// Get an entity reference property (1-1 or M-1) for the given entity.
        /// </summary>
        /// <param name="entity">Entity object</param>
        /// <param name="property">Property information</param>
        public static EntityReferenceProperty<ITrackable>
            GetEntityReferenceProperty(this ITrackable entity, PropertyInfo property)
        {
            return entity.GetEntityReferenceProperty<ITrackable>(property);
        }

        /// <summary>
        /// Pick only properties of type entity reference.
        /// </summary>
        /// <typeparam name="TEntity">Type of entity</typeparam>
        /// <param name="navigationProperties">All nagivation properties</param>
        public static IEnumerable<EntityReferenceProperty<TEntity>>
            OfReferenceType<TEntity>(this IEnumerable<EntityNavigationProperty> navigationProperties)
            where TEntity : class, ITrackable
        {
            return navigationProperties.SelectMany(np => np.AsReferenceProperty<TEntity>());
        }

        /// <summary>
        /// Pick only properties of type entity reference.
        /// </summary>
        /// <param name="navigationProperties">All nagivation properties</param>
        public static IEnumerable<EntityReferenceProperty>
            OfReferenceType(this IEnumerable<EntityNavigationProperty> navigationProperties)
        {
            return navigationProperties.OfReferenceType<ITrackable>();
        }

        /// <summary>
        /// Pick only properties of type entity collection.
        /// </summary>
        /// <typeparam name="TEntityCollection">Type of entity collection</typeparam>
        /// <param name="navigationProperties">All nagivation properties</param>
        public static IEnumerable<EntityCollectionProperty<TEntityCollection>>
            OfCollectionType<TEntityCollection>(this IEnumerable<EntityNavigationProperty> navigationProperties)
            where TEntityCollection : class
        {
            return navigationProperties.SelectMany(np => np.AsCollectionProperty<TEntityCollection>());
        }

        /// <summary>
        /// Pick only properties of type entity collection.
        /// </summary>
        /// <param name="navigationProperties">All nagivation properties</param>
        public static IEnumerable<EntityCollectionProperty>
            OfCollectionType(this IEnumerable<EntityNavigationProperty> navigationProperties)
        {
            return navigationProperties.OfCollectionType<IEnumerable<ITrackable>>();
        }

        /// <summary>
        /// Default implementation of INavigationPropertyInspector used if an entity doesn't provide
        /// its own implementation.
        /// DefaultNavigationPropertyInspector simply loops over all entity properties
        /// and yields those, whose values are either ITrackable or IEnumerable&lt;ITrackable&gt;.
        /// </summary>
        private sealed class DefaultNavigationPropertyInspector : INavigationPropertyInspector
        {
            private readonly ITrackable Entity;

            public DefaultNavigationPropertyInspector(ITrackable entity)
            {
                this.Entity = entity;
            }

            public IEnumerable<EntityNavigationProperty> GetNavigationProperties()
            {
                foreach (var prop in Entity.GetType().GetProperties())
                {
                    // 1-1 and M-1 properties
                    if (typeof(ITrackable).IsAssignableFrom(prop.PropertyType))
                    {
                        var trackableRef = prop.GetValue(Entity, null) as ITrackable;
                        yield return new EntityReferenceProperty(prop, trackableRef);
                    }

                    // 1-M and M-M properties
                    if (typeof(IEnumerable<ITrackable>).IsAssignableFrom(prop.PropertyType))
                    {
                        var items = prop.GetValue(Entity, null) as IEnumerable<ITrackable>;
                        yield return new EntityCollectionProperty(prop, items);
                    }
                }
            }
        }
    }
}


<|start_filename|>Samples/VS2013/WcfSample/WcfSample.Service.Core/ICustomerService.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.ServiceModel;
using System.Threading.Tasks;
using WcfSample.Shared.Entities.Net45.Models;
using WcfSerializationHelper;

namespace WcfSample.Service.Core
{
    [ServiceContract(Namespace = "urn:trackable-entities:samples")]
    [DataContractSerializerPreserveReferences] // Configure serializer to handle cycles
    public interface ICustomerService
    {
        [OperationContract]
        Task<IEnumerable<Customer>> GetCustomers();

        [OperationContract]
        Task<Customer> GetCustomer(string id);
        
        [OperationContract]
        Task<Customer> UpdateCustomer(Customer customer);
        
        [OperationContract]
        Task<Customer> CreateCustomer(Customer customer);
        
        [OperationContract]
        Task<bool> DeleteCustomer(string id);
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Patterns/WebApiSample.Service.Persistence/Repositories/IOrderRepository.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.Threading.Tasks;
using TrackableEntities.Patterns;
using WebApiSample.Service.Entities.Models;

namespace WebApiSample.Service.Persistence.Repositories
{
    public interface IOrderRepository : IRepository<Order>, IRepositoryAsync<Order>
    {
        Task<IEnumerable<Order>> GetOrders();
        Task<IEnumerable<Order>> GetOrders(string customerId);
        Task<Order> GetOrder(int id);
        Task<bool> DeleteOrder(int id);
    }
}


<|start_filename|>Extensions/VS2015/Output/Extract/ItemTemplates/ExampleUnitOfWork/ExampleUnitOfWork.cs<|end_filename|>
﻿using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Threading;
using System.Threading.Tasks;
using TrackableEntities.Patterns.EF6;

namespace $rootnamespace$
{
    // Implements I$safeitemname$ in the Persistence project
    public class $safeitemname$ : UnitOfWork, I$safeitemname$
    {
        // TODO: Add read-only fields for each entity repository interface
        //private readonly IEntityRepository _entityRepository;

		// TODO: Rename IDatabaseContext to match context interface
		// TODO: Add parameters for each repository interface
        public $safeitemname$(IDatabaseContext context
            /* , IEntityRepository entityRepository */) :
            base(context as DbContext)
        {
		    // TODO: Initizlialize each entity repository field
            //_entityRepository = entityRepository;
        }

        // TODO: Add read-only property for each entity repository interface
        //public IEntityRepository EntityRepository
        //{
        //    get { return _entityRepository; }
        //}

        public override int SaveChanges()
        {
            try
            {
                return base.SaveChanges();
            }
            catch (DbUpdateConcurrencyException concurrencyException)
            {
                throw new UpdateConcurrencyException(concurrencyException.Message,
                    concurrencyException);
            }
            catch (DbUpdateException updateException)
            {
                throw new UpdateException(updateException.Message,
                    updateException);
            }
        }

        public override Task<int> SaveChangesAsync()
        {
            return SaveChangesAsync(CancellationToken.None);
        }

        public override Task<int> SaveChangesAsync(CancellationToken cancellationToken)
        {
            try
            {
                return base.SaveChangesAsync(cancellationToken);
            }
            catch (DbUpdateConcurrencyException concurrencyException)
            {
                throw new UpdateConcurrencyException(concurrencyException.Message,
                    concurrencyException);
            }
            catch (DbUpdateException updateException)
            {
                throw new UpdateException(updateException.Message, 
                    updateException);
            }
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Inheritance/SampleWebApi.Inheritance.Shared.Entities/Models/DiscontinuedProduct.cs<|end_filename|>
using System;

namespace SampleWebApi.Inheritance.Shared.Entities.Models
{
    public partial class DiscontinuedProduct : Product
    {
		public DateTime? DiscontinuedDate
		{ 
			get { return _DiscontinuedDate; }
			set
			{
                if (Equals(value, _DiscontinuedDate)) return;
                _DiscontinuedDate = value;
                NotifyPropertyChanged();
			}
		}
		private DateTime? _DiscontinuedDate;
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Patterns/WebApiSample.Service.EF/Mapping/EmployeeMap.cs<|end_filename|>
using System.Data.Entity.ModelConfiguration;
using WebApiSample.Service.Entities.Models;

namespace WebApiSample.Service.EF.Mapping
{
    public class EmployeeMap : EntityTypeConfiguration<Employee>
    {
        public EmployeeMap()
        {
            // Primary Key
            this.HasKey(t => t.EmployeeId);

            // Properties
            this.Property(t => t.LastName)
                .IsRequired()
                .HasMaxLength(20);

            this.Property(t => t.FirstName)
                .IsRequired()
                .HasMaxLength(20);

            this.Property(t => t.City)
                .HasMaxLength(15);

            this.Property(t => t.Country)
                .HasMaxLength(15);

            // Table & Column Mappings
            this.ToTable("Employee");
            this.Property(t => t.EmployeeId).HasColumnName("EmployeeId");
            this.Property(t => t.LastName).HasColumnName("LastName");
            this.Property(t => t.FirstName).HasColumnName("FirstName");
            this.Property(t => t.BirthDate).HasColumnName("BirthDate");
            this.Property(t => t.HireDate).HasColumnName("HireDate");
            this.Property(t => t.City).HasColumnName("City");
            this.Property(t => t.Country).HasColumnName("Country");

            // Tracking Properties
			this.Ignore(t => t.TrackingState);
			this.Ignore(t => t.ModifiedProperties);
			this.Ignore(t => t.EntityIdentifier);

            // Relationships
            this.HasMany(t => t.Territories)
                .WithMany(t => t.Employees)
                .Map(m =>
                    {
                        m.ToTable("EmployeeTerritories");
                        m.MapLeftKey("EmployeeId");
                        m.MapRightKey("TerritoryId");
                    });


        }
    }
}


<|start_filename|>Extensions/VS2012/Deploy/TrackableEntities.TemplateWizard/RootWizard.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.IO;
using System.Reflection;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.TemplateWizard;

// This assembly must be signed and either installed in the GAC
// or included as Content in a VSIX project.
// Then it is referenced from vstemplates.
// Custom replacement can be used in projects and files.

namespace TrackableEntities.TemplateWizard
{
    // Root wizard is used by root project vstemplate
    public class RootWizard : IWizard
    {
        // Use to communicate $saferootprojectname$ to ChildWizard
        public static Dictionary<string, string> GlobalDictionary =
            new Dictionary<string, string>();

        // Fields
        private DTE2 _dte2;
        private string _templateName;

        // Add global replacement parameters
        public void RunStarted(object automationObject, 
            Dictionary<string, string> replacementsDictionary, 
            WizardRunKind runKind, object[] customParams)
        {
            // Place "$saferootprojectname$ in the global dictionary.
            // Copy from $safeprojectname$ passed in my root vstemplate
            GlobalDictionary["$saferootprojectname$"] = replacementsDictionary["$safeprojectname$"];

            // Get template name
            _templateName = Path.GetFileNameWithoutExtension((string)customParams[0]);

            // Get DTE
            _dte2 = (DTE2)automationObject;
        }

        public void BeforeOpeningFile(ProjectItem projectItem)
        {
        }

        public void ProjectFinishedGenerating(Project project)
        {
        }

        public void ProjectItemFinishedGenerating(ProjectItem projectItem)
        {
        }

        public void RunFinished()
        {
            // Add ReadMe file to solution folder
            var solution = (Solution2)_dte2.Solution;
            solution.AddSolutionFolder("Solution Items");
            
            // Copy readme file to solution directory and add to solution folder
            string sourceReadMePath = GetTemplateReadMePath(_templateName);
            string destReadMePath = GetDestReadMePath(solution, _templateName);
            File.Copy(sourceReadMePath, destReadMePath);
            if (File.Exists(destReadMePath))
                _dte2.ItemOperations.AddExistingItem(destReadMePath);

            // Set startup project
            string extension = null;
            if (_templateName == Constants.ProjectTemplates.TrackableWcfService)
                extension = ".Service.Web";
            else if (_templateName == Constants.ProjectTemplates.TrackableWebApi)
                extension = ".WebApi";
            if (extension != null)
            {
                Project startupProject = GetProject(extension);
                if (startupProject != null)
                {
                    _dte2.Solution.SolutionBuild.StartupProjects = startupProject.UniqueName;
                }
            }
        }

        public bool ShouldAddProjectItem(string filePath)
        {
            return true;
        }

        private string GetDestReadMePath(Solution2 solution, string templateName)
        {
            var solutionPath = solution.Properties.Item("Path").Value as string;
            if (string.IsNullOrWhiteSpace(solutionPath)) return null;
            string solutionDir = new FileInfo(solutionPath).DirectoryName;
            if (string.IsNullOrWhiteSpace(solutionDir)) return null;
            string readMeFileName = GetReadMeFileName(templateName);
            string destReadMePath = Path.Combine(solutionDir, readMeFileName);
            return destReadMePath;
        }

        private string GetReadMeFileName(string templateName)
        {
            switch (templateName)
            {
                case Constants.ProjectTemplates.TrackableWcfService:
                    return Constants.ReadMeFiles.TrackableWcf;
                case Constants.ProjectTemplates.TrackableWebApi:
                    return Constants.ReadMeFiles.TrackableWebApi;
                default:
                    return null;
            }
        }

        private string GetTemplateReadMePath(string templateName)
        {
            string readMeFileName = GetReadMeFileName(templateName);
            if (readMeFileName == null) return null;
            string templateReadMePath = GetTemplateFilePath(readMeFileName);
            return templateReadMePath;
        }

        private string GetTemplateFilePath(string fileName)
        {
            string dirPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string parentPath = Directory.GetParent(dirPath).FullName;
            string filePath = Path.Combine(parentPath, fileName);
            return filePath;
        }

        private Project GetProject(string extension)
        {
            string projectName = GlobalDictionary["$saferootprojectname$"] + extension;
            foreach (Project project in _dte2.Solution.Projects)
            {
                if (Path.GetFileNameWithoutExtension(project.FullName).Equals(projectName))
                {
                    return project;
                }
            }
            return null;
        }

    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/Features/RetreiveEntities.feature.cs<|end_filename|>
﻿// ------------------------------------------------------------------------------
//  <auto-generated>
//      This code was generated by SpecFlow (http://www.specflow.org/).
//      SpecFlow Version:1.9.0.77
//      SpecFlow Generator Version:1.9.0.0
//      Runtime Version:4.0.30319.34209
// 
//      Changes to this file may cause incorrect behavior and will be lost if
//      the code is regenerated.
//  </auto-generated>
// ------------------------------------------------------------------------------
#region Designer generated code
#pragma warning disable
namespace TrackableEntities.Tests.Acceptance.Features
{
    using TechTalk.SpecFlow;
    
    
    [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.9.0.77")]
    [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    public partial class RetreiveEntitiesFeature : Xunit.IUseFixture<RetreiveEntitiesFeature.FixtureData>, System.IDisposable
    {
        
        private static TechTalk.SpecFlow.ITestRunner testRunner;
        
#line 1 "RetreiveEntities.feature"
#line hidden
        
        public RetreiveEntitiesFeature()
        {
            this.TestInitialize();
        }
        
        public static void FeatureSetup()
        {
            testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner();
            TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Retreive Entities", "In order to retrieve entities\r\nAs a Web API client\r\nI want to retrieve entities f" +
                    "rom the database", ProgrammingLanguage.CSharp, ((string[])(null)));
            testRunner.OnFeatureStart(featureInfo);
        }
        
        public static void FeatureTearDown()
        {
            testRunner.OnFeatureEnd();
            testRunner = null;
        }
        
        public virtual void TestInitialize()
        {
        }
        
        public virtual void ScenarioTearDown()
        {
            testRunner.OnScenarioEnd();
        }
        
        public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo)
        {
            testRunner.OnScenarioStart(scenarioInfo);
        }
        
        public virtual void ScenarioCleanup()
        {
            testRunner.CollectScenarioErrors();
        }
        
        public virtual void SetFixture(RetreiveEntitiesFeature.FixtureData fixtureData)
        {
        }
        
        void System.IDisposable.Dispose()
        {
            this.ScenarioTearDown();
        }
        
        [Xunit.FactAttribute()]
        [Xunit.TraitAttribute("FeatureTitle", "Retreive Entities")]
        [Xunit.TraitAttribute("Description", "Retreive Customers")]
        public virtual void RetreiveCustomers()
        {
            TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Retreive Customers", new string[] {
                        "retrieve_entities"});
#line 7
this.ScenarioSetup(scenarioInfo);
#line hidden
            TechTalk.SpecFlow.Table table1 = new TechTalk.SpecFlow.Table(new string[] {
                        "CustomerId",
                        "CustomerName"});
            table1.AddRow(new string[] {
                        "ABCD",
                        "Test Customer ABCD"});
            table1.AddRow(new string[] {
                        "EFGH",
                        "Test Customer EFGH"});
#line 8
 testRunner.Given("the following customers", ((string)(null)), table1, "Given ");
#line 12
 testRunner.When("I submit a GET request for customers", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line 13
 testRunner.Then("the request should return the customers", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
            this.ScenarioCleanup();
        }
        
        [Xunit.FactAttribute()]
        [Xunit.TraitAttribute("FeatureTitle", "Retreive Entities")]
        [Xunit.TraitAttribute("Description", "Retreive Customer Orders")]
        public virtual void RetreiveCustomerOrders()
        {
            TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Retreive Customer Orders", new string[] {
                        "retrieve_entities"});
#line 16
this.ScenarioSetup(scenarioInfo);
#line hidden
            TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] {
                        "CustomerId",
                        "CustomerName"});
            table2.AddRow(new string[] {
                        "ABCD",
                        "Test Customer ABCD"});
#line 17
 testRunner.Given("the following customers", ((string)(null)), table2, "Given ");
#line hidden
            TechTalk.SpecFlow.Table table3 = new TechTalk.SpecFlow.Table(new string[] {
                        "CustomerId"});
            table3.AddRow(new string[] {
                        "ABCD"});
#line 20
 testRunner.And("the following customer orders", ((string)(null)), table3, "And ");
#line 23
 testRunner.When("I submit a GET request for customer orders", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line 24
 testRunner.Then("the request should return the orders", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
            this.ScenarioCleanup();
        }
        
        [Xunit.FactAttribute()]
        [Xunit.TraitAttribute("FeatureTitle", "Retreive Entities")]
        [Xunit.TraitAttribute("Description", "Retreive Order")]
        public virtual void RetreiveOrder()
        {
            TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Retreive Order", new string[] {
                        "retrieve_entities"});
#line 27
this.ScenarioSetup(scenarioInfo);
#line hidden
            TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] {
                        "CustomerId",
                        "CustomerName"});
            table4.AddRow(new string[] {
                        "ABCD",
                        "Test Customer ABCD"});
#line 28
 testRunner.Given("the following customers", ((string)(null)), table4, "Given ");
#line hidden
            TechTalk.SpecFlow.Table table5 = new TechTalk.SpecFlow.Table(new string[] {
                        "CustomerId"});
            table5.AddRow(new string[] {
                        "ABCD"});
#line 31
 testRunner.And("the following customer orders", ((string)(null)), table5, "And ");
#line 34
 testRunner.When("I submit a GET request for an order", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line 35
 testRunner.Then("the request should return the orders", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
            this.ScenarioCleanup();
        }
        
        [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.9.0.77")]
        [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
        public class FixtureData : System.IDisposable
        {
            
            public FixtureData()
            {
                RetreiveEntitiesFeature.FeatureSetup();
            }
            
            void System.IDisposable.Dispose()
            {
                RetreiveEntitiesFeature.FeatureTearDown();
            }
        }
    }
}
#pragma warning restore
#endregion


<|start_filename|>Samples/VS2013/WebApiSample.ModelFirst/WebApiSample.Service.Entities/Order.cs<|end_filename|>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace WebApiSample.Service.Entities
{
    using System;
    using System.Collections.Generic;
    using TrackableEntities;
    
    public partial class Order : ITrackable, IMergeable
    {
        public Order()
        {
            this.OrderDetails = new List<OrderDetail>();
        }
    
        public int OrderId { get; set; }
        public string CustomerId { get; set; }
        public Nullable<System.DateTime> OrderDate { get; set; }
        public Nullable<System.DateTime> ShippedDate { get; set; }
        public Nullable<int> ShipVia { get; set; }
        public Nullable<decimal> Freight { get; set; }
    
        public Customer Customer { get; set; }
        public ICollection<OrderDetail> OrderDetails { get; set; }
    
        public TrackingState TrackingState { get; set; }
        public ICollection<string> ModifiedProperties { get; set; }
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Inheritance/SampleWebApi.Inheritance.Shared.Entities/Models/Product.cs<|end_filename|>
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using TrackableEntities.Client;

namespace SampleWebApi.Inheritance.Shared.Entities.Models
{
    public partial class Product : EntityBase
    {
		public int ProductId
		{ 
			get { return _ProductId; }
			set
			{
				if (Equals(value, _ProductId)) return;
				_ProductId = value;
				NotifyPropertyChanged();
			}
		}
		private int _ProductId;

        [Required]
        [StringLength(40)]
		public string ProductName
		{ 
			get { return _ProductName; }
			set
			{
				if (Equals(value, _ProductName)) return;
				_ProductName = value;
				NotifyPropertyChanged();
			}
		}
		private string _ProductName;

		public int? CategoryId
		{ 
			get { return _CategoryId; }
			set
			{
				if (Equals(value, _CategoryId)) return;
				_CategoryId = value;
				NotifyPropertyChanged();
			}
		}
		private int? _CategoryId;

        [Column(TypeName = "money")]
		public decimal? UnitPrice
		{ 
			get { return _UnitPrice; }
			set
			{
				if (Equals(value, _UnitPrice)) return;
				_UnitPrice = value;
				NotifyPropertyChanged();
			}
		}
		private decimal? _UnitPrice;

        [Column(TypeName = "timestamp")]
        [MaxLength(8)]
        [Timestamp]
		public byte[] RowVersion
		{ 
			get { return _RowVersion; }
			set
			{
				if (Equals(value, _RowVersion)) return;
				_RowVersion = value;
				NotifyPropertyChanged();
			}
		}
		private byte[] _RowVersion;

		public Category Category
		{
			get { return _Category; }
			set
			{
				if (Equals(value, _Category)) return;
				_Category = value;
				CategoryChangeTracker = _Category == null ? null
					: new ChangeTrackingCollection<Category> { _Category };
				NotifyPropertyChanged();
			}
		}
		private Category _Category;
		private ChangeTrackingCollection<Category> CategoryChangeTracker { get; set; }
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/ClientEntities/Customer.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using TrackableEntities.Client;

namespace TrackableEntities.Tests.Acceptance.ClientEntities
{
    [JsonObject(IsReference = true)]
    public class Customer : EntityBase
    {
        private string _customerId;
        public string CustomerId
        {
            get { return _customerId; }
            set
            {
                if (value == _customerId) return;
                _customerId = value;
                NotifyPropertyChanged();
            }
        }

        private string _customerName;
        public string CustomerName
        {
            get { return _customerName; }
            set
            {
                if (value == _customerName) return;
                _customerName = value;
                NotifyPropertyChanged();
            }
        }

        private string _data;
        public string Data
        {
            get { return _data; }
            set
            {
                if (value == _data) return;
                _data = value;
                NotifyPropertyChanged();
            }
        }

        private string _territoryId;
        public string TerritoryId
        {
            get { return _territoryId; }
            set
            {
                _territoryId = value;
                NotifyPropertyChanged();
            }
        }

        private CustomerSetting _customerSetting;
        public CustomerSetting CustomerSetting
        {
            get { return _customerSetting; }
            set
            {
                if (value == _customerSetting) return;
                _customerSetting = value;
                CustomerSettingChangeTracker = _customerSetting == null ? null
                    : new ChangeTrackingCollection<CustomerSetting> { _customerSetting };
                NotifyPropertyChanged();
            }
        }
        private ChangeTrackingCollection<CustomerSetting> CustomerSettingChangeTracker { get; set; }

        private Territory _territory;
        public Territory Territory
        {
            get { return _territory; }
            set
            {
                if (value == _territory) return;
                _territory = value;
                TerritoryChangeTracker = _territory == null ? null
                    : new ChangeTrackingCollection<Territory> { _territory };
            }
        }
        private ChangeTrackingCollection<Territory> TerritoryChangeTracker { get; set; }
    }
}


<|start_filename|>Extensions/Common/Wizards/TrackableEntities.TemplateWizard/EntitiesChildWizard.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using EnvDTE;
using Microsoft.VisualStudio.TemplateWizard;

namespace TrackableEntities.TemplateWizard
{
    public class EntitiesChildWizard : ChildWizard
    {
        protected override void ProcessEntitiesTemplate(
            Dictionary<string, string> replacementsDictionary, string templateName)
        {
            // Get $entitiestempaltename$ dictionary entry and return if null or not present
            string entitiesTemplateName = EntitiesWizard.RootDictionary[Constants.DictionaryEntries.EntitiesTemplateName];
            if (string.IsNullOrWhiteSpace(entitiesTemplateName)) return;
            string[] entitiesTemplateNames = entitiesTemplateName.Split('|');

            // Get destination directory
            DirectoryInfo directory = null;
            string directoryPath = replacementsDictionary[Constants.DictionaryEntries.DestinationDirectory];
            if (!string.IsNullOrWhiteSpace(directoryPath))
                directory = new DirectoryInfo(directoryPath);

            // If present and not null, back out if does not match current template name
            if (!entitiesTemplateNames.Contains(templateName, StringComparer.InvariantCultureIgnoreCase))
            {
                // Include Shared Portable Data project when indicated
                if (RootWizard.RootDictionary[Constants.DictionaryEntries.ParentWizardName] == Constants.ParentWizards.RootWizard &&
                    templateName.Equals(Constants.EntitiesTemplates.SharedPortableData) &&
                    entitiesTemplateName.Equals(Constants.EntitiesTemplates.SharedPortable, StringComparison.InvariantCultureIgnoreCase))
                { /* Do nothing */ }
                else
                {
                    // Delete folder and cancel
                    if (directory != null) directory.Delete();
                    throw new WizardBackoutException();
                }
            }

            // Set root dictionary values
            var projectName = replacementsDictionary[Constants.DictionaryEntries.SafeProjectName];
            EntitiesWizard.RootDictionary[Constants.DictionaryEntries.SafeProjectName] = projectName;
            EntitiesWizard.RootDictionary[Constants.DictionaryEntries.OriginalDestinationDirectory] =
                replacementsDictionary[Constants.DictionaryEntries.DestinationDirectory];

            // Set destination directory
            var directoryInfo = new DirectoryInfo(replacementsDictionary
                [Constants.DictionaryEntries.DestinationDirectory]).Parent;
            if (directoryInfo != null && directoryInfo.Parent != null)
            {
                string destDirectory = Path.Combine(directoryInfo.Parent.FullName, projectName);
                EntitiesWizard.RootDictionary[Constants.DictionaryEntries.DestinationDirectory] = destDirectory;
                replacementsDictionary[Constants.DictionaryEntries.DestinationDirectory] = destDirectory;
            }
        }

        protected override void MoveGeneratedProject(ref Project project)
        {
            // Return if parent is root wizard
            if (RootWizard.RootDictionary[Constants.DictionaryEntries.ParentWizardName] ==
                Constants.ParentWizards.RootWizard) return;

            // Get directory and project info
            var origDestDirectory = EntitiesWizard.RootDictionary[Constants.DictionaryEntries.OriginalDestinationDirectory];
            var newDestDirectory = EntitiesWizard.RootDictionary[Constants.DictionaryEntries.DestinationDirectory];
            var projectName = EntitiesWizard.RootDictionary[Constants.DictionaryEntries.SafeProjectName];
            
            // Move project up a level
            if (!string.IsNullOrWhiteSpace(origDestDirectory) && 
                !string.IsNullOrWhiteSpace(newDestDirectory) && 
                !string.IsNullOrWhiteSpace(projectName))
            {
                Dte2.Solution.Remove(project);
                Directory.Move(origDestDirectory, newDestDirectory);
                string newDestProject = Path.Combine(newDestDirectory, projectName + ".csproj");
                Dte2.Solution.AddFromFile(newDestProject);
                project = Dte2.Solution.Projects.Cast<Project>()
                    .Single(p => p.Name == projectName);
            }
        }
    }
}


<|start_filename|>Build/Scripts/TrackableEntities.Patterns.cmd<|end_filename|>
@echo On
set debug=%1

REM Set Variables:
set config=%Configuration%
if "%Configuration%" == "" (
   set config=Release
)
set version=%PackageVersion%
set name=TrackableEntities.Patterns
set source=Source\%name%
set logs=Build\Logs\%name%
set output=Build\Output\%name%

REM Build:
if "%debug%"=="1" pause
mkdir "%logs%"
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild "%source%\%name%.csproj" /p:Configuration="%config%" /m /v:M /fl /flp:LogFile="%logs%\msbuild.log";Verbosity=Normal /nr:false
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit

REM Package:
mkdir "%output%"
Source\.nuget\nuget.exe pack "%source%\%name%.csproj" -symbols -o "%output%" -p Configuration="%config%";PackageVersion="%version%"
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit

<|start_filename|>Samples/VS2013/WebApiSample.Relations/WebApiSample.Service.Entities/Models/Mapping/OrderDetailMap.cs<|end_filename|>

using System.Data.Entity.ModelConfiguration;
using System.ComponentModel.DataAnnotations.Schema;

namespace WebApiSample.Service.Entities.Models.Mapping
{
    public class OrderDetailMap : EntityTypeConfiguration<OrderDetail>
    {
        public OrderDetailMap()
        {
            // Primary Key
            this.HasKey(t => t.OrderDetailId);

            // Properties
            // Table & Column Mappings
            this.ToTable("OrderDetail");
            this.Property(t => t.OrderDetailId).HasColumnName("OrderDetailId");
            this.Property(t => t.OrderId).HasColumnName("OrderId");
            this.Property(t => t.ProductId).HasColumnName("ProductId");
            this.Property(t => t.UnitPrice).HasColumnName("UnitPrice");
            this.Property(t => t.Quantity).HasColumnName("Quantity");
            this.Property(t => t.Discount).HasColumnName("Discount");

            // Tracking Properties
			this.Ignore(t => t.TrackingState);
			this.Ignore(t => t.ModifiedProperties);
			this.Ignore(t => t.EntityIdentifier);

            // Relationships
            this.HasRequired(t => t.Order)
                .WithMany(t => t.OrderDetails)
                .HasForeignKey(d => d.OrderId);
            this.HasRequired(t => t.Product)
                .WithMany(t => t.OrderDetails)
                .HasForeignKey(d => d.ProductId);

        }
    }
}


<|start_filename|>Extensions/VS2012/Deploy/TrackableEntities.TemplateWizard/ChildWizard.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Windows.Forms;
using EnvDTE;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.TemplateWizard;
using NuGet.VisualStudio;

namespace TrackableEntities.TemplateWizard
{
    public class ChildWizard : IWizard
    {
        [Import]
        internal IVsTemplateWizard Wizard { get; set; }

        // Retrieve global replacement parameters
        public void RunStarted(object automationObject,
            Dictionary<string, string> replacementsDictionary,
            WizardRunKind runKind, object[] customParams)
        {
            // Add custom parameters.
            replacementsDictionary.Add("$saferootprojectname$",
                RootWizard.GlobalDictionary["$saferootprojectname$"]);

            // Init NuGet Wizard
            Initialize(automationObject);
            Wizard.RunStarted(automationObject, replacementsDictionary, runKind, customParams);
        
        }
        public void BeforeOpeningFile(ProjectItem projectItem)
        {
            Wizard.BeforeOpeningFile(projectItem);
        }

        public void ProjectFinishedGenerating(Project project)
        {
            Wizard.ProjectFinishedGenerating(project);
        }

        public void ProjectItemFinishedGenerating(ProjectItem projectItem)
        {
            Wizard.ProjectItemFinishedGenerating(projectItem);
        }

        public void RunFinished()
        {
            Wizard.RunFinished();
        }

        public bool ShouldAddProjectItem(string filePath)
        {
            return Wizard.ShouldAddProjectItem(filePath);
        }

        private void Initialize(object automationObject)
        {
            using (var provider = new ServiceProvider((IServiceProvider)automationObject))
            {
                var service = (IComponentModel)provider.GetService(typeof(SComponentModel));
                using (var container = new CompositionContainer(new[] { service.DefaultExportProvider }))
                {
                    container.ComposeParts(new object[] { this });
                }
            }
            if (Wizard == null)
            {
                MessageBox.Show("NuGet Package Manager not available.");
                throw new WizardBackoutException("NuGet Package Manager not available.");
            }
        }
    }
}


<|start_filename|>Source/Tests/TrackableEntities.EF.5.Tests/NorthwindModels/HolidayPromo.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace TrackableEntities.EF.Tests.NorthwindModels
{
    public partial class HolidayPromo : Promo, ITrackable
    {
        public string HolidayName { get; set; }

        [NotMapped]
        public TrackingState TrackingState { get; set; }
        [NotMapped]
        public ICollection<string> ModifiedProperties { get; set; }
    }
}


<|start_filename|>Extensions/VS2015/Output/Extract/ItemTemplates/EntityController/EntityController.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using TrackableEntities.Common;
using $entitiesNamespace$;
using $baseNamespace$.Service.Persistence.Exceptions;
using $baseNamespace$.Service.Persistence.UnitsOfWork;

namespace $rootnamespace$
{
	public class $safeitemname$ : ApiController
	{
        // TODO: Rename IExampleUnitOfWork to match Unit of Work Interface added to Persistence project
		private readonly IExampleUnitOfWork _unitOfWork;

        // TODO: Rename IExampleUnitOfWork parameter
		public $safeitemname$(IExampleUnitOfWork unitOfWork)
		{
			_unitOfWork = unitOfWork;
		}

		// GET api/$entityName$
		[ResponseType(typeof(IEnumerable<$entityName$>))]
		public async Task<IHttpActionResult> Get$entitySetName$()
		{
			IEnumerable<$entityName$> entities = await _unitOfWork.$entityName$Repository.Get$entitySetName$();	
			return Ok(entities);
		}

		// GET api/$entityName$/5
		[ResponseType(typeof($entityName$))]
		public async Task<IHttpActionResult> Get$entityName$(int id)
		{
			$entityName$ entity = await _unitOfWork.$entityName$Repository.Get$entityName$(id);	
			if (entity == null)
			{
				return NotFound();
			}
			return Ok(entity);
		}

		// POST api/$entityName$
		[ResponseType(typeof($entityName$))]
		public async Task<IHttpActionResult> Post$entityName$($entityName$ entity)
		{
			if (!ModelState.IsValid)
			{
				return BadRequest(ModelState);
			}

			_unitOfWork.$entityName$Repository.Insert(entity);

			try
			{
				await _unitOfWork.SaveChangesAsync();
			}
			catch (UpdateException)
			{
				if (_unitOfWork.$entityName$Repository.Find(entity.$entityName$Id) == null)
				{
					return Conflict();
				}
				throw;
			}

            await _unitOfWork.$entityName$Repository.LoadRelatedEntitiesAsync(entity);
			entity.AcceptChanges();

			return CreatedAtRoute("DefaultApi", new { id = entity.$entityName$Id }, entity);
		}

		// PUT api/$entityName$
		[ResponseType(typeof($entityName$))]
		public async Task<IHttpActionResult> Put$entityName$($entityName$ entity)
		{
			if (!ModelState.IsValid)
			{
				return BadRequest(ModelState);
			}

			_unitOfWork.$entityName$Repository.Update(entity);

			try
			{
				await _unitOfWork.SaveChangesAsync();
			}
			catch (UpdateConcurrencyException)
			{
				if (_unitOfWork.$entityName$Repository.Find(entity.$entityName$Id) == null)
				{
					return Conflict();
				}
				throw;
			}

            await _unitOfWork.$entityName$Repository.LoadRelatedEntitiesAsync(entity);
			entity.AcceptChanges();
			return Ok(entity);
		}

		// DELETE api/$entityName$/5
		public async Task<IHttpActionResult> Delete$entityName$(int id)
		{
			bool result = await _unitOfWork.$entityName$Repository.Delete$entityName$(id);	
            if (!result) return Ok();

			try
			{
				await _unitOfWork.SaveChangesAsync();
			}
			catch (UpdateConcurrencyException)
			{
				if (_unitOfWork.$entityName$Repository.Find(id) == null)
				{
					return Conflict();
				}
				throw;
			}

			return Ok();
		}

		protected override void Dispose(bool disposing)
		{
			if (disposing)
			{
				var disposable = _unitOfWork as IDisposable;
				if (disposable != null)
					disposable.Dispose();
			}
			base.Dispose(disposing);
		}
    }
}


<|start_filename|>Samples/VS2013/WebApiSample/WebApiSample.Service.Entities/Models/Category.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using TrackableEntities;

namespace WebApiSample.Service.Entities.Models
{
    [Table("Category")]
    public partial class Category : ITrackable, IMergeable
    {
        public Category()
        {
            Products = new List<Product>();
        }

        public int CategoryId { get; set; }

        [Required]
        [StringLength(15)]
        public string CategoryName { get; set; }

        public ICollection<Product> Products { get; set; }

		[NotMapped]
        public TrackingState TrackingState { get; set; }

		[NotMapped]
        public ICollection<string> ModifiedProperties { get; set; }

		[NotMapped]
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm.WpfClient/Services/ICustomerServiceAgent.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using WebApiSample.Mvvm.Client.Entities.Models;

namespace WebApiSample.Mvvm.WpfClient
{
    public interface ICustomerServiceAgent
    {
        Task<IEnumerable<Customer>> GetCustomers();
    }
}


<|start_filename|>Source/Tests/TrackableEntities.EF.5.Tests/Contexts/NorthwindDbContext.cs<|end_filename|>
﻿
using System.Data.Entity;
using TrackableEntities.EF.Tests.NorthwindModels;

namespace TrackableEntities.EF.Tests.Contexts
{
    public class NorthwindDbContext : DbContext
    {
#if EF_6
        private const string TestDbName = "NorthwindTestDbv6";        
#else
        private const string TestDbName = "NorthwindTestDbv5";        
#endif

        public NorthwindDbContext(string connectionString)
            : base(connectionString)
        {
        }

        public NorthwindDbContext(CreateDbOptions createDbOptions = CreateDbOptions.CreateDatabaseIfNotExists)
            : base(TestDbName)
        {
            switch (createDbOptions)
            {
                case CreateDbOptions.DropCreateDatabaseAlways:
                    Database.SetInitializer(new DropCreateDatabaseAlways<NorthwindDbContext>());
                    break;
                case CreateDbOptions.DropCreateDatabaseSeed:
                    Database.SetInitializer(new NorthwindDbInitializer());
                    break;
                case CreateDbOptions.DropCreateDatabaseIfModelChanges:
                    Database.SetInitializer(new DropCreateDatabaseIfModelChanges<NorthwindDbContext>());
                    break;
                default:
                    Database.SetInitializer(new DropCreateDatabaseAlways<NorthwindDbContext>());
                    break;
            }
        }
        
        public DbSet<Category> Categories { get; set; }
        public DbSet<Product> Products { get; set; }
        public DbSet<Promo> Promos { get; set; }
        public DbSet<ProductInfo> ProductInfos { get; set; }
        public DbSet<Customer> Customers { get; set; }
        public DbSet<CustomerAddress> CustomerAddresses { get; set; }
        public DbSet<CustomerSetting> CustomerSettings { get; set; }
        public DbSet<Order> Orders { get; set; }
        public DbSet<OrderDetail> OrderDetails { get; set; }
        public DbSet<Employee> Employees { get; set; }
        public DbSet<Territory> Territories { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<CustomerSetting>()
                .HasRequired(x => x.Customer)
                .WithOptional(x => x.CustomerSetting);
            modelBuilder.Entity<Promo>().ToTable("Promos");
            modelBuilder.Entity<HolidayPromo>().ToTable("HolidayPromos");
            modelBuilder.Entity<ProductInfo>().ToTable("ProductInfos");
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Inheritance/SampleWebApi.Inheritance.ConsoleClient/Program.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Threading.Tasks;
using Newtonsoft.Json;
using TrackableEntities;
using TrackableEntities.Client;
using SampleWebApi.Inheritance.Shared.Entities.Models;

namespace SampleWebApi.Inheritance.ConsoleClient
{
    class Program
    {
        static void Main(string[] args)
        {
            // Main method

            Console.WriteLine("Press Enter to start");
            Console.ReadLine();

            // Create http client
            const string serviceBaseAddress = "http://localhost:" + "49640" + "/";
            var client = new HttpClient { BaseAddress = new Uri(serviceBaseAddress) };

            List<Product> products = GetProducts(client).ToList();
            foreach (var p in products)
                PrintProduct(p);

            // Select individual product
            Console.WriteLine("\nProduct to update {ProductId}:");
            int productId = int.Parse(Console.ReadLine());
            var product = products.Single(p => p.ProductId == productId);

            // Track changes
            var changeTracker = new ChangeTrackingCollection<Product>(product);

            // Update product
            product.UnitPrice++;

            // Get changes
            var changedProduct = changeTracker.GetChanges().SingleOrDefault();

            // Submit changes
            Product updatedProduct;
            if (product is DiscontinuedProduct)
                updatedProduct = UpdateEntity(client, (DiscontinuedProduct)product);
            else
                updatedProduct = UpdateEntity(client, product);

            // Merge changes
            changeTracker.MergeChanges(updatedProduct);

            Console.WriteLine("Updated product:");
            PrintProduct(product);

            // Keep console open
            Console.WriteLine("\nPress any key to exit");
            Console.ReadKey(true);
        }

        private static IEnumerable<Category> GetCategories(HttpClient client)
        {
            const string request = "api/Category";
            var response = client.GetAsync(request).Result;
            response.EnsureSuccessStatusCode();
            var result = response.Content.ReadAsAsync<IEnumerable<Category>>().Result;
            return result;
        }

        private static IEnumerable<Product> GetProducts
            (HttpClient client)
        {
            string request = "api/Product";
            var response = client.GetAsync(request).Result;
            response.EnsureSuccessStatusCode();

            var result = ReadContentAsAsync<IEnumerable<Product>>(response).Result;
            return result;
        }

        private static T UpdateEntity<T>(HttpClient client, T entity)
        {
            string request = "api/Product";
            var content = GetObjectContent(entity);
            var response = client.PutAsync(request, content).Result;
            response.EnsureSuccessStatusCode();

            var result = ReadContentAsAsync<T>(response).Result;
            return result;
        }

        private static async Task<T> ReadContentAsAsync<T>(HttpResponseMessage response)
        {
            var jsonFormatter = new JsonMediaTypeFormatter { SerializerSettings = { TypeNameHandling = TypeNameHandling.Auto } };
            var result = await response.Content.ReadAsAsync<T>(new MediaTypeFormatter[] { jsonFormatter });
            return result;
        }

        private static ObjectContent<T> GetObjectContent<T>(T entity)
        {
            var jsonFormatter = new JsonMediaTypeFormatter { SerializerSettings = { TypeNameHandling = TypeNameHandling.Auto } };
            var content = new ObjectContent<T>(entity, jsonFormatter);
            return content;
        }

        private static void PrintCategory(Category c)
        {
            Console.WriteLine("{0} {1}",
                c.CategoryId,
                c.CategoryName);
        }

        private static void PrintProduct(Product p)
        {
            // See if this is a discontinued product
            var discProduct = p as DiscontinuedProduct;

            Console.WriteLine("{0} {1} {2} {3}",
                p.ProductId,
                p.ProductName,
                p.UnitPrice.GetValueOrDefault().ToString("C"),
                discProduct != null
                    ? string.Format("Discontinued: {0}",
                    discProduct.DiscontinuedDate.GetValueOrDefault().ToShortDateString())
                    : string.Empty);
        }
    }
}


<|start_filename|>Extensions/Common/Wizards/ItemTemplateParametersWizard/IModelTypes.cs<|end_filename|>
﻿using System;

namespace ItemTemplateParametersWizard
{
    public interface IModelTypes
    {
        ModelTypesDialogInfo ModelTypesDialogInfo { get; }
    }
}


<|start_filename|>Source/Tests/TrackableEntities.Client.Tests.Entities/FamilyModels/Family.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace TrackableEntities.Client.Tests.Entities.FamilyModels
{
    [JsonObject]
    public class Family : EntityBase
    {
        private Parent _mother;
        private Parent _father;
        private Child _child;

        public Parent Mother
        {
            get { return _mother; }
            set
            {
                if (value == _mother) return;
                _mother = value;
                MotherChangeTracker = _mother == null ? null : new ChangeTrackingCollection<Parent>(_mother);
                NotifyPropertyChanged(() => Mother);
            }
        }
        private ChangeTrackingCollection<Parent> MotherChangeTracker { get; set; }


        public Parent Father
        {
            get { return _father; }
            set
            {
                if (value == _father) return;
                _father = value;
                FatherChangeTracker = _father == null ? null : new ChangeTrackingCollection<Parent> {_father};
                NotifyPropertyChanged(() => Father);

            }
        }
        private ChangeTrackingCollection<Parent> FatherChangeTracker { get; set; }


        public Child Child
        {
            get { return _child; }
            set
            {
                if (value == _child) return;
                _child = value;
                ChildChangeTracker = _child == null ? null : new ChangeTrackingCollection<Child> {_child};
                NotifyPropertyChanged(() => Child);
            }
        }
        private ChangeTrackingCollection<Child> ChildChangeTracker { get; set; }
    }
}


<|start_filename|>Source/Tests/TrackableEntities.EF.5.Tests/NorthwindModels/Area.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TrackableEntities.EF.Tests.NorthwindModels
{
    public partial class Area : ITrackable
    {
        [Key]
        public int AreaId { get; set; }
        public string AreaName { get; set; }
        public List<Territory> Territories { get; set; }

        [NotMapped]
        public TrackingState TrackingState { get; set; }
        [NotMapped]
        public ICollection<string> ModifiedProperties { get; set; }
    }
}


<|start_filename|>Samples/VS2012/WebApiSample/WebApiSample.Service.Entities/Models/Customer.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using TrackableEntities;

namespace WebApiSample.Service.Entities.Models
{
    [JsonObject(IsReference = true)]
    [DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
    public partial class Customer : ITrackable
    {
        public Customer()
        {
            this.Orders = new List<Order>();
        }

        [DataMember]
        public string CustomerId { get; set; }
        [DataMember]
        public string CompanyName { get; set; }
        [DataMember]
        public string ContactName { get; set; }
        [DataMember]
        public string City { get; set; }
        [DataMember]
        public string Country { get; set; }
        [DataMember]
        public CustomerSetting CustomerSetting { get; set; }
        [DataMember]
        public List<Order> Orders { get; set; }

        [DataMember]
        public TrackingState TrackingState { get; set; }
        [DataMember]
        public ICollection<string> ModifiedProperties { get; set; }
        [JsonProperty, DataMember]
        private Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm/WebApiSample.Mvvm.WebApi/Areas/HelpPage/Views/Help/DisplayTemplates/SimpleTypeModelDescription.cshtml<|end_filename|>
@using WebApiSample.Mvvm.WebApi.Areas.HelpPage.ModelDescriptions
@model SimpleTypeModelDescription
@Model.Documentation

<|start_filename|>Extensions/VS2015/Output/Extract/ItemTemplates/IExampleUnitOfWork/IExampleUnitOfWork.cs<|end_filename|>
﻿using System;
using TrackableEntities.Patterns;

namespace $rootnamespace$
{
    public interface $safeitemname$ : IUnitOfWork, IUnitOfWorkAsync
    {
        // TODO: Add read-only properties for each entity repository interface
        //IEntityRepository EntityRepository { get; }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample/WebApiSample.Client.Entities.Net45/Models/Category.cs<|end_filename|>
using TrackableEntities.Client;

namespace WebApiSample.Client.Entities.Models
{
    public partial class Category : EntityBase
    {
        public Category()
        {
            Products = new ChangeTrackingCollection<Product>();
        }

		public int CategoryId
		{ 
			get { return _CategoryId; }
			set
			{
				if (Equals(value, _CategoryId)) return;
				_CategoryId = value;
				NotifyPropertyChanged();
			}
		}
		private int _CategoryId;

		public string CategoryName
		{ 
			get { return _CategoryName; }
			set
			{
				if (Equals(value, _CategoryName)) return;
				_CategoryName = value;
				NotifyPropertyChanged();
			}
		}
		private string _CategoryName;

		public ChangeTrackingCollection<Product> Products
		{
			get { return _Products; }
			set
			{
				if (Equals(value, _Products)) return;
				_Products = value;
				NotifyPropertyChanged();
			}
		}
		private ChangeTrackingCollection<Product> _Products;
    }
}


<|start_filename|>Samples/VS2013/WcfSample/WcfSample.ConsoleClient/IOrderService.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Threading.Tasks;
using WcfSample.Shared.Entities.Net45.Models;

namespace WcfSample.Client.ConsoleApp
{
    [ServiceContract(Namespace = "urn:trackable-entities:samples")]
    public interface IOrderService
    {
        [OperationContract(Name = "GetOrders")]
        Task<IEnumerable<Order>> GetOrdersAsync();

        [OperationContract(Name = "GetCustomerOrders")]
        Task<IEnumerable<Order>> GetCustomerOrdersAsync(string customerId);

        [OperationContract(Name = "GetOrder")]
        Task<Order> GetOrderAsync(int id);

        [OperationContract(Name = "UpdateOrder")]
        Task<Order> UpdateOrderAsync(Order order);

        [OperationContract(Name = "CreateOrder")]
        Task<Order> CreateOrderAsync(Order order);

        [OperationContract(Name = "DeleteOrder")]
        Task<bool> DeleteOrderAsync(int id);
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/ClientEntities/Employee.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using TrackableEntities.Client;

namespace TrackableEntities.Tests.Acceptance.ClientEntities
{
    [JsonObject(IsReference = true)]
    public class Employee : EntityBase
    {
        private int _employeeId;
        public int EmployeeId
        {
            get { return _employeeId; }
            set
            {
                if (value == _employeeId) return;
                _employeeId = value;
                NotifyPropertyChanged();
            }
        }
        
        private string _lastName;
        public string LastName
        {
            get { return _lastName; }
            set
            {
                if (value == _lastName) return;
                _lastName = value;
                NotifyPropertyChanged();
            }
        }

        private string _firstName;
        public string FirstName
        {
            get { return _firstName; }
            set
            {
                if (value == _firstName) return;
                _firstName = value;
                NotifyPropertyChanged();
            }
        }

        private DateTime? _birthDate;
        public DateTime? BirthDate
        {
            get { return _birthDate; }
            set
            {
                if (value == _birthDate) return;
                _birthDate = value;
                NotifyPropertyChanged();
            }
        }

        private DateTime? _hireDate;
        public DateTime? HireDate
        {
            get { return _hireDate; }
            set
            {
                if (value == _hireDate) return;
                _hireDate = value;
                NotifyPropertyChanged();
            }
        }

        private string _city;
        public string City
        {
            get { return _city; }
            set
            {
                if (value == _city) return;
                _city = value;
                NotifyPropertyChanged();
            }
        }

        private string _country;
        public string Country
        {
            get { return _country; }
            set
            {
                if (value == _country) return;
                _country = value;
                NotifyPropertyChanged();
            }
        }

        private ChangeTrackingCollection<Territory> _territories;
        public ChangeTrackingCollection<Territory> Territories
        {
            get { return _territories; }
            set
            {
                if (value != null) value.Parent = this;
                if (Equals(value, _territories)) return;
                _territories = value;
                NotifyPropertyChanged();
            }
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample/WebApiSample.ConsoleClient/Program.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using AspnetWebApi2Helpers.Serialization;
using TrackableEntities.Client;
using WebApiSample.Shared.Entities.Portable.Models;

namespace WebApiSample.Client.ConsoleApp
{
    class Program
    {
        static void Main()
        {
            // Get media type formatter
            MediaTypeFormatter formatter;
            string acceptHeader;
            GetFormatter(out formatter, out acceptHeader);

            // TODO: Address for Web API service (replace port number)
            const string serviceBaseAddress = "http://localhost:" + "58527" + "/";
            var client = new HttpClient { BaseAddress = new Uri(serviceBaseAddress) };
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(acceptHeader));

            // Get customers
            Console.WriteLine("Customers:");
            IEnumerable<Customer> customers = GetCustomers(client, formatter);
            if (customers == null) return;
            foreach (var c in customers)
                PrintCustomer(c);

            // Get orders for a customer
            Console.WriteLine("\nGet customer orders {CustomerId}:");
            string customerId = Console.ReadLine();
            if (!customers.Any(c => string.Equals(c.CustomerId, customerId, StringComparison.OrdinalIgnoreCase)))
            {
                Console.WriteLine("Invalid customer id: {0}", customerId.ToUpper());
                return;
            }
            IEnumerable<Order> orders = GetCustomerOrders(client, customerId, formatter);
            foreach (var o in orders)
                PrintOrder(o);

            // Get an order
            Console.WriteLine("\nGet an order {OrderId}:");
            int orderId = int.Parse(Console.ReadLine());
            if (!orders.Any(o => o.OrderId == orderId))
            {
                Console.WriteLine("Invalid order id: {0}", orderId);
                return;
            }
            Order order = GetOrder(client, orderId, formatter);
            PrintOrderWithDetails(order);

            // Create a new order
            Console.WriteLine("\nPress Enter to create a new order for {0}",
                customerId.ToUpper());
            Console.ReadLine();

            var newOrder = new Order
            {
                CustomerId = customerId,
                OrderDate = DateTime.Today,
                ShippedDate = DateTime.Today.AddDays(1),
                OrderDetails = new ChangeTrackingCollection<OrderDetail>
                    {
                        new OrderDetail { ProductId = 1, Quantity = 5, UnitPrice = 10 },
                        new OrderDetail { ProductId = 2, Quantity = 10, UnitPrice = 20 },
                        new OrderDetail { ProductId = 4, Quantity = 40, UnitPrice = 40 }
                    }
            };
            var createdOrder = CreateOrder(client, newOrder, formatter);
            PrintOrderWithDetails(createdOrder);

            // Update the order
            Console.WriteLine("\nPress Enter to update order details");
            Console.ReadLine();

            // Start change-tracking the order
            var changeTracker = new ChangeTrackingCollection<Order>(createdOrder);

            // Modify order details
            createdOrder.OrderDetails[0].UnitPrice++;
            createdOrder.OrderDetails.RemoveAt(1);
            createdOrder.OrderDetails.Add(new OrderDetail
            {
                OrderId = createdOrder.OrderId,
                ProductId = 3,
                Quantity = 15,
                UnitPrice = 30
            });

            // Submit changes
            var changedOrder = changeTracker.GetChanges().SingleOrDefault();
            var updatedOrder = UpdateOrder(client, changedOrder, formatter);

            // Merge changes
            changeTracker.MergeChanges(updatedOrder);
            Console.WriteLine("Updated order:");
            PrintOrderWithDetails(createdOrder);

            // Delete the order
            Console.WriteLine("\nPress Enter to delete the order");
            Console.ReadLine();
            DeleteOrder(client, createdOrder);

            // Verify order was deleted
            var deleted = VerifyOrderDeleted(client, createdOrder.OrderId);
            Console.WriteLine(deleted ?
                "Order was successfully deleted" :
                "Order was not deleted");

            // Keep console open
            Console.WriteLine("Press any key to exit");
            Console.ReadKey(true);
        }

        private static bool GetFormatter(out MediaTypeFormatter formatter, out string acceptHeader)
        {
            Console.WriteLine("\nSelect a formatter: Json {J}, Xml {X}, or exit {Enter}");
            //Console.WriteLine("\nSelect a formatter: Json {J}, Xml {X}, Protobuf {P}, or exit {Enter}");
            string selection = Console.ReadLine().ToUpper();

            if (selection == "J")
            {
                var jsonFormatter = new JsonMediaTypeFormatter();
                jsonFormatter.JsonPreserveReferences();
                formatter = jsonFormatter;
                acceptHeader = "application/json";
            }
            else if (selection == "X")
            {
                formatter = new XmlDataContractSerializerFormatter();
                acceptHeader = "application/xml";
            }
            //else if (selection == "P")
            //{
            //    var protoFormatter = new ProtoBufFormatter();
            //    protoFormatter.ProtobufPreserveReferences(typeof(Category).Assembly);
            //    formatter = protoFormatter;
            //    acceptHeader = MediaTypes.Protobuf;
            //}
            else
            {
                formatter = null;
                acceptHeader = null;
                return false;
            }
            return true;
        }

        private static IEnumerable<Customer> GetCustomers(HttpClient client, MediaTypeFormatter formatter)
        {
            const string request = "api/Customer";
            var response = client.GetAsync(request).Result;
            response.EnsureSuccessStatusCode();
            var result = response.Content.ReadAsAsync<IEnumerable<Customer>>(new[] { formatter }).Result;
            return result;
        }

        private static IEnumerable<Order> GetCustomerOrders
            (HttpClient client, string customerId, MediaTypeFormatter formatter)
        {
            string request = "api/Order?customerId=" + customerId;
            var response = client.GetAsync(request).Result;
            response.EnsureSuccessStatusCode();
            var result = response.Content.ReadAsAsync<IEnumerable<Order>>(new[] { formatter }).Result;
            return result;
        }

        private static Order GetOrder(HttpClient client, int orderId, MediaTypeFormatter formatter)
        {
            string request = "api/Order/" + orderId;
            var response = client.GetAsync(request).Result;
            response.EnsureSuccessStatusCode();
            var result = response.Content.ReadAsAsync<Order>(new[] { formatter }).Result;
            return result;
        }

        private static Order CreateOrder(HttpClient client, Order order, MediaTypeFormatter formatter)
        {
            string request = "api/Order";
            var response = client.PostAsync(new Uri(request, UriKind.Relative), order, formatter).Result;
            response.EnsureSuccessStatusCode();
            var result = response.Content.ReadAsAsync<Order>(new[] { formatter }).Result;
            return result;
        }

        private static Order UpdateOrder(HttpClient client, Order order, MediaTypeFormatter formatter)
        {
            string request = "api/Order";
            var response = client.PutAsync(new Uri(request, UriKind.Relative), order, formatter).Result;
            response.EnsureSuccessStatusCode();
            var result = response.Content.ReadAsAsync<Order>().Result;
            return result;
        }

        private static void DeleteOrder(HttpClient client, Order order)
        {
            string request = "api/Order/" + order.OrderId;
            var response = client.DeleteAsync(request);
            response.Result.EnsureSuccessStatusCode();
        }

        private static bool VerifyOrderDeleted(HttpClient client, int orderId)
        {
            string request = "api/Order/" + orderId;
            var response = client.GetAsync(request).Result;
            if (response.IsSuccessStatusCode) return false;
            return true;
        }

        private static void PrintCustomer(Customer c)
        {
            Console.WriteLine("{0} {1} {2} {3}",
                c.CustomerId,
                c.CompanyName,
                c.ContactName,
                c.City);
        }

        private static void PrintOrder(Order o)
        {
            Console.WriteLine("{0} {1}",
                o.OrderId,
                o.OrderDate.GetValueOrDefault().ToShortDateString());
        }

        private static void PrintOrderWithDetails(Order o)
        {
            Console.WriteLine("{0} {1}",
                o.OrderId,
                o.OrderDate.GetValueOrDefault().ToShortDateString());
            foreach (var od in o.OrderDetails)
            {
                Console.WriteLine("\t{0} {1} {2} {3}",
                    od.OrderDetailId,
                    od.Product.ProductName,
                    od.Quantity,
                    od.UnitPrice.ToString("c"));
            }
        }
    }
}


<|start_filename|>Samples/VS2012/WebApiSample/WebApiSample.Service.WebApi/Controllers/OrdersController.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using TrackableEntities;
using TrackableEntities.EF5;
using TrackableEntities.Common;
using WebApiSample.Service.Entities.Contexts;
using WebApiSample.Service.Entities.Models;

namespace WebApiSample.Service.WebApi.Controllers
{
    public class OrdersController : ApiController
    {
        private readonly NorthwindSlimContext _dbContext = new NorthwindSlimContext();

        // GET api/Orders
        public IEnumerable<Order> GetOrders()
        {
            IEnumerable<Order> orders = _dbContext.Orders
			    .Include(o => o.Customer)
                .Include("OrderDetails.Product") // Include details with product
                .ToList();

            return orders;
        }

        // GET api/Order?customerId=ABCD
        public IEnumerable<Order> GetOrders(string customerId)
        {
            IEnumerable<Order> orders = _dbContext.Orders
                .Include(o => o.Customer)
                .Include("OrderDetails.Product") // Include details with product
                .Where(o => o.CustomerId == customerId)
                .ToList();
            return orders;
        }

        // GET api/Orders/5
        public Order GetOrder(int id)
        {
            Order order = _dbContext.Orders
			    .Include(o => o.Customer)
                .Include("OrderDetails.Product") // Include details with product
                .SingleOrDefault(o => o.OrderId == id);

            if (order == null)
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
            }

            return order;
        }

        // POST api/Orders
        public HttpResponseMessage PostOrder(Order order)
        {
            if (!ModelState.IsValid)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }

            order.TrackingState = TrackingState.Added;
            _dbContext.ApplyChanges(order);

            try
            {
                _dbContext.SaveChanges();
            }
            catch (DbUpdateException ex)
            {
                if (_dbContext.Orders.Any(o => o.OrderId == order.OrderId))
                {
	                return Request.CreateErrorResponse(HttpStatusCode.Conflict, ex);
                }
                throw;
            }

            _dbContext.LoadRelatedEntities(order);
            order.AcceptChanges();

            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, order);
            response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = order.OrderId }));
            return response;
        }

        // PUT api/Orders
        public HttpResponseMessage PutOrder(Order order)
        {
            if (!ModelState.IsValid)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }

            _dbContext.ApplyChanges(order);

            try
            {
                _dbContext.SaveChanges();
            }
            catch (DbUpdateConcurrencyException ex)
            {
                if (!_dbContext.Orders.Any(o => o.OrderId == order.OrderId))
                {
	                return Request.CreateErrorResponse(HttpStatusCode.Conflict, ex);
                }
                throw;
            }

			_dbContext.LoadRelatedEntities(order);
			order.AcceptChanges();

            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, order);
            return response;
        }

        // DELETE api/Orders/5
        public HttpResponseMessage DeleteOrder(int id)
        {
            Order order = _dbContext.Orders
                .Include(o => o.OrderDetails) // Include details
                .SingleOrDefault(o => o.OrderId == id);
            if (order == null)
            {
                return Request.CreateResponse(HttpStatusCode.OK);
            }

			order.TrackingState = TrackingState.Deleted;
			_dbContext.ApplyChanges(order);

            try
            {
                _dbContext.SaveChanges();
            }
            catch (DbUpdateConcurrencyException ex)
            {
                if (!_dbContext.Orders.Any(o => o.OrderId == order.OrderId))
                {
	                return Request.CreateErrorResponse(HttpStatusCode.Conflict, ex);
                }
                throw;
            }

            return Request.CreateResponse(HttpStatusCode.OK);
        }

        protected override void Dispose(bool disposing)
        {
            _dbContext.Dispose();
            base.Dispose(disposing);
        }
    }
}

<|start_filename|>Samples/VS2013/WebApiSample.Relations/WebApiSample.Service.Entities/Models/Category.cs<|end_filename|>
using System;
using System.Collections.Generic;
using TrackableEntities;

namespace WebApiSample.Service.Entities.Models
{
    public partial class Category : ITrackable, IMergeable
    {
        public Category()
        {
            this.Products = new List<Product>();
        }

        public int CategoryId { get; set; }
        public string CategoryName { get; set; }
        public List<Product> Products { get; set; }

        public TrackingState TrackingState { get; set; }
        public ICollection<string> ModifiedProperties { get; set; }
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Extensions/Common/Wizards/TrackableEntities.ItemWizard/ModelReflectionHelper.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Diagnostics;
using System.Linq;
using System.IO;
using System.Globalization;
using System.Security.Policy;
using System.Reflection;
using ItemTemplateParametersWizard;

namespace TrackableEntities.ItemWizard
{
    public static class ModelReflectionHelper
    {
        private static string _assemblyFullName;

        public static List<ModelTypeInfo> GetModelTypes(FileInfo assemblyLocation)
        {
            _assemblyFullName = assemblyLocation.FullName;

            if (string.IsNullOrEmpty(assemblyLocation.Directory.FullName))
            {
                throw new InvalidOperationException("Directory can't be null or empty.");
            }

            if (!Directory.Exists(assemblyLocation.Directory.FullName))
            {
                throw new InvalidOperationException(
                   string.Format(CultureInfo.CurrentCulture,
                   "Directory not found {0}",
                   assemblyLocation.Directory.FullName));
            }

            AppDomain childDomain = BuildChildDomain(AppDomain.CurrentDomain);

            // Use of assembly resolver is needed for VS 2013 Update 2
            AppDomain.CurrentDomain.AssemblyResolve += ChildDomainOnAssemblyResolve;

            try
            {
                // Create asm loader in child AppDomain
                Type loaderType = typeof(AssemblyLoader);
                object loaderObj = childDomain
                    .CreateInstanceFrom(loaderType.Assembly.Location,
                        loaderType.FullName).Unwrap();

                // Method will be null if there are loading problems
                //var method = loaderObj.GetType().GetMethod("GetVersionInfo",
                //    BindingFlags.Instance | BindingFlags.Public);
                //object info = method.Invoke(loaderObj, null);

                // Get info on types for specified assembly
                var loader = (AssemblyLoader)loaderObj;
                loader.LoadAssembly(assemblyLocation.FullName);
                var types = loader.GetModelTypeInfo(
                    assemblyLocation.Directory.FullName);
                return types;
            }

            finally
            {
                AppDomain.Unload(childDomain);
            }

        }

        private static Assembly ChildDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
        {
            try
            {
                Assembly assembly = Assembly.Load(args.Name);
                if (assembly != null) return assembly;
            }
            // ReSharper disable once EmptyGeneralCatchClause
            catch { } // Ignore load error

            // In case Load doesn't work, fall back to LoadFrom
            return Assembly.LoadFrom(_assemblyFullName);
        }

        private static AppDomain BuildChildDomain(AppDomain parentDomain)
        {
            var evidence = new Evidence(parentDomain.Evidence);
            AppDomainSetup setup = parentDomain.SetupInformation;
            return AppDomain.CreateDomain("DiscoveryRegion", evidence, setup);
        }

        private static bool InheritsFrom(this Type type, Type comparedType)
        {
            // Test for null
            if (type == null || comparedType == null) return false;

            // Test for interfaces
            if (comparedType.IsInterface)
            {
                return type.GetInterfaces().Any(t => t.FullName == comparedType.FullName);
            }

            // Test for base class
             return (type == comparedType||type.IsSubclassOf(comparedType));
        }

        class AssemblyLoader : MarshalByRefObject
        {
            // Call via reflection to diagnose loading problems
            internal string GetVersionInfo()
            {
                return ".NET Version: " + Environment.Version.ToString() + "\r\n" +
                "wwReflection Assembly: " + typeof(AssemblyLoader).Assembly.CodeBase.Replace("file:///", "").Replace("/", "\\") + "\r\n" +
                "Assembly Cur Dir: " + Directory.GetCurrentDirectory() + "\r\n" +
                "ApplicationBase: " + AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "\r\n" +
                "App Domain: " + AppDomain.CurrentDomain.FriendlyName + "\r\n";
            }
            
            internal List<ModelTypeInfo> GetModelTypeInfo(string path)
            {
                var types = new List<ModelTypeInfo>();

                var directory = new DirectoryInfo(path);
                ResolveEventHandler resolveEventHandler =
                    (s, e) => OnReflectionOnlyResolve(
                        e, directory);

                AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve
                    += resolveEventHandler;

                Assembly reflectionOnlyAssembly =
                    AppDomain.CurrentDomain.
                        ReflectionOnlyGetAssemblies().First();

                foreach(Type type in reflectionOnlyAssembly.GetTypes())
                {
                    var modelType = ModelType.Other;
                    if (type.InheritsFrom(typeof(ITrackable)))
                        modelType = ModelType.Trackable;
                    else if (type.InheritsFrom(typeof(DbContext)))
                        modelType = ModelType.DbContext;
                    types.Add(new ModelTypeInfo
                    {
                        Namespace = type.Namespace,
                        Name = type.Name, 
                        ModelType = modelType,
                        DisplayName = string.Format("{0} ({1})",
                            type.Name, type.Namespace)
                    });
                }

                AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve
                    -= resolveEventHandler;
                return types;
            }

            private Assembly OnReflectionOnlyResolve(
                ResolveEventArgs args, DirectoryInfo directory)
            {
                Assembly loadedAssembly =
                    AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies()
                        .FirstOrDefault(
                          asm => string.Equals(asm.FullName, args.Name,
                              StringComparison.OrdinalIgnoreCase));

                if (loadedAssembly != null)
                {
                    return loadedAssembly;
                }

                var assemblyName = new AssemblyName(args.Name);
                string dependentAssemblyFilename =
                    Path.Combine(directory.FullName,
                    assemblyName.Name + ".dll");

                if (File.Exists(dependentAssemblyFilename))
                {
                    return Assembly.ReflectionOnlyLoadFrom(
                        dependentAssemblyFilename);
                }
                return Assembly.ReflectionOnlyLoad(args.Name);
            }

            internal void LoadAssembly(string assemblyPath)
            {
                try
                {
                    Assembly.ReflectionOnlyLoadFrom(assemblyPath);
                }
                catch (FileNotFoundException)
                {
                    /* Continue loading assemblies even if an assembly
                     * can not be loaded in the new AppDomain. */
                }
            }
        }
    }
}



<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm.WpfClient/Services/CustomerServiceAgent.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using WebApiSample.Mvvm.Client.Entities.Models;

namespace WebApiSample.Mvvm.WpfClient
{
    public class CustomerServiceAgent : ICustomerServiceAgent
    {
        public async Task<IEnumerable<Customer>> GetCustomers()
        {
            const string request = "api/Customer";
            var response = await ServiceProxy.Instance.GetAsync(request);
            response.EnsureSuccessStatusCode();
            var result = await response.Content.ReadAsAsync<IEnumerable<Customer>>(new[] { ServiceProxy.Formatter });
            return result;
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Patterns/WebApiSample.WebApi/Controllers/CustomerController.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using TrackableEntities.Common;
using WebApiSample.Service.Entities.Models;
using WebApiSample.Service.Persistence.Exceptions;
using WebApiSample.Service.Persistence.UnitsOfWork;

namespace WebApiSample.Service.WebApi.Controllers
{
	public class CustomerController : ApiController
	{
		private readonly INorthwindUnitOfWork _unitOfWork;

		public CustomerController(INorthwindUnitOfWork unitOfWork)
		{
			_unitOfWork = unitOfWork;
		}

		// GET api/Customer
		[ResponseType(typeof(IEnumerable<Customer>))]
		public async Task<IHttpActionResult> GetCustomers()
		{
			IEnumerable<Customer> customers = await _unitOfWork.CustomerRepository.GetCustomers();	
			return Ok(customers);
		}

		// GET api/Customer/5
		[ResponseType(typeof(Customer))]
		public async Task<IHttpActionResult> GetCustomer(string id)
		{
			Customer customer = await _unitOfWork.CustomerRepository.GetCustomer(id);	
			if (customer == null)
			{
				return NotFound();
			}
			return Ok(customer);
		}

        // POST api/Customer
        [ResponseType(typeof(Customer))]
        public async Task<IHttpActionResult> PostCustomer(Customer customer)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            _unitOfWork.CustomerRepository.Insert(customer);

            try
            {
                // Save and accept changes
                await _unitOfWork.SaveChangesAsync();
            }
            catch (UpdateException)
            {
                if (_unitOfWork.CustomerRepository.Find(customer.CustomerId) == null)
                {
                    return Conflict();
                }
                throw;
            }

            // Load related entities and accept changes
            await _unitOfWork.CustomerRepository.LoadRelatedEntitiesAsync(customer);
            customer.AcceptChanges();

            return CreatedAtRoute("DefaultApi", new { id = customer.CustomerId }, customer);
        }

        // PUT api/Customer
		[ResponseType(typeof(Customer))]
		public async Task<IHttpActionResult> PutCustomer(Customer customer)
		{
			if (!ModelState.IsValid)
			{
				return BadRequest(ModelState);
			}

            _unitOfWork.CustomerRepository.Update(customer);
            
            try
			{
				await _unitOfWork.SaveChangesAsync();
			}
			catch (UpdateConcurrencyException)
			{
				if (_unitOfWork.CustomerRepository.Find(customer.CustomerId) == null)
				{
                    return Conflict();
				}
				throw;
			}

            await _unitOfWork.CustomerRepository.LoadRelatedEntitiesAsync(customer);
            customer.AcceptChanges();
            return Ok(customer);
        }

		// DELETE api/Customer/5
		public async Task<IHttpActionResult> DeleteCustomer(string id)
		{
			bool result = await _unitOfWork.CustomerRepository.DeleteAsync(id);
			if (!result) return Ok();

			try
			{
				await _unitOfWork.SaveChangesAsync();
			}
			catch (UpdateConcurrencyException)
			{
				if (_unitOfWork.CustomerRepository.Find(id) == null)
				{
                    return Conflict();
				}
				throw;
			}

            return Ok();
        }

		protected override void Dispose(bool disposing)
		{
			if (disposing)
			{
				var disposable = _unitOfWork as IDisposable;
				if (disposable != null)
					disposable.Dispose();
			}
			base.Dispose(disposing);
		}
	}
}

<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm/WebApiSample.Mvvm.Service.Entities/Models/CustomerSetting.cs<|end_filename|>
using System;
using System.Collections.Generic;
using TrackableEntities;

namespace WebApiSample.Mvvm.Service.Entities.Models
{
    public partial class CustomerSetting : ITrackable, IMergeable
    {
        public string CustomerId { get; set; }
        public string Setting { get; set; }
        public Customer Customer { get; set; }

        public TrackingState TrackingState { get; set; }
        public ICollection<string> ModifiedProperties { get; set; }
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Samples/VS2012/WcfSample/WcfSample.Service.Entities/Models/Mapping/TerritoryMap.cs<|end_filename|>
using System.Data.Entity.ModelConfiguration;

namespace WcfSample.Service.Entities.Models.Mapping
{
    public class TerritoryMap : EntityTypeConfiguration<Territory>
    {
        public TerritoryMap()
        {
            // Primary Key
            this.HasKey(t => t.TerritoryId);

            // Properties
            this.Property(t => t.TerritoryId)
                .IsRequired()
                .HasMaxLength(20);

            this.Property(t => t.TerritoryDescription)
                .IsRequired()
                .HasMaxLength(50);

            // Table & Column Mappings
            this.ToTable("Territory");
            this.Property(t => t.TerritoryId).HasColumnName("TerritoryId");
            this.Property(t => t.TerritoryDescription).HasColumnName("TerritoryDescription");

            // Tracking Properties
			this.Ignore(t => t.TrackingState);
			this.Ignore(t => t.ModifiedProperties);
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Inheritance/SampleWebApi.Inheritance.Shared.Entities/Contexts/NorthwindSlimInheritance.cs<|end_filename|>
using System.Data.Entity;
using SampleWebApi.Inheritance.Shared.Entities.Models;

namespace SampleWebApi.Inheritance.Shared.Entities.Contexts
{
    public partial class NorthwindSlimInheritance : DbContext
    {
        static NorthwindSlimInheritance()
        {
            // To seed database, delete the database then uncomment:
            //Database.SetInitializer(new NorthwindSlimDatabaseInitializer());

            Database.SetInitializer(new NullDatabaseInitializer<NorthwindSlimInheritance>());
        }

        public NorthwindSlimInheritance()
            : base("name=NorthwindSlimInheritance")
        {
            Configuration.ProxyCreationEnabled = false;
        }

        public virtual DbSet<Category> Categories { get; set; }
        public virtual DbSet<Product> Products { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Product>()
                .Property(e => e.UnitPrice)
                .HasPrecision(19, 4);

            modelBuilder.Entity<Product>()
                .Property(e => e.RowVersion)
                .IsFixedLength();

            ModelCreating(modelBuilder);
        }

        partial void ModelCreating(DbModelBuilder modelBuilder);
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Patterns/WebApiSample.Service.Persistence/Repositories/ICustomerRepository.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using TrackableEntities.Patterns;
using WebApiSample.Service.Entities.Models;

namespace WebApiSample.Service.Persistence.Repositories
{
    public interface ICustomerRepository : IRepository<Customer>, IRepositoryAsync<Customer>
    {
        Task<Customer> GetCustomer(string id);
        Task<IEnumerable<Customer>> GetCustomers();
    }
}


<|start_filename|>Build/nuget-proget-symbols.cmd<|end_filename|>
rem VS Setup: http://inedo.com/support/tutorials/debug-into-internal-nuget-packages-with-proget

set source=http://localhost:81/nuget/Default
set version=2.5.0
set key=Admin:Admin

NuGet.exe push Output\TrackableEntities.Common\TrackableEntities.Common.%version%.symbols.nupkg %key% -Source %source%
NuGet.exe push Output\TrackableEntities.Client\TrackableEntities.Client.%version%.symbols.nupkg %key% -Source %source%
NuGet.exe push Output\TrackableEntities.Client.Net4\TrackableEntities.Client.Net4.%version%.symbols.nupkg %key% -Source %source%
NuGet.exe push Output\TrackableEntities.EF.5\TrackableEntities.EF.5.%version%.symbols.nupkg %key% -Source %source%
NuGet.exe push Output\TrackableEntities.EF.6\TrackableEntities.EF.6.%version%.symbols.nupkg %key% -Source %source%
NuGet.exe push Output\TrackableEntities.Patterns\TrackableEntities.Patterns.%version%.symbols.nupkg %key% -Source %source%
NuGet.exe push Output\TrackableEntities.Patterns.EF.6\TrackableEntities.Patterns.EF.6.%version%.symbols.nupkg %key% -Source %source%


<|start_filename|>Source/TrackableEntities.Patterns/IUnitOfWorkAsync.cs<|end_filename|>
﻿using System;
using System.Threading;
using System.Threading.Tasks;

namespace TrackableEntities.Patterns
{
    /// <summary>
    /// Unit of work for committing changes across one or more repositories asynchronously.
    /// </summary>
    public interface IUnitOfWorkAsync
    {
        /// <summary>
        /// Saves changes made to one or more repositories.
        /// </summary>
        /// <returns>A task that represents the asynchronous save operation. The task result contains the number of objects saved.</returns>
        Task<int> SaveChangesAsync();

        /// <summary>
        /// Saves changes made to one or more repositories.
        /// </summary>
        /// <param name="cancellationToken">A CancellationToken to observe while waiting for the task to complete.</param>
        /// <returns>A task that represents the asynchronous save operation. The task result contains the number of objects saved.</returns>
        Task<int> SaveChangesAsync(CancellationToken cancellationToken);
    }
}


<|start_filename|>Source/TrackableEntities.EF.5/InterceptorExtensions.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.Data.Entity;
#if EF_6
#else
using System.Data;
#endif

#if EF_6
namespace TrackableEntities.EF6
#else
namespace TrackableEntities.EF5
#endif
{
    /// <summary>
    /// Extension methods for <see cref="DbContext"/> and <see cref="InterceptorPool"/> with fluent API allowing
    /// to add inteceptors (instances of <see cref="IStateInterceptor"/>) to <see cref="DbContextExtensions.ApplyChanges(DbContext, ITrackable)"/>.
    /// </summary>
    public static class InterceptorExtensions
    {
        /// <summary>
        /// Injects interceptor implementing <see cref="IStateInterceptor"/> intto <see cref="DbContextExtensions.ApplyChanges(DbContext, ITrackable)"/>.
        /// </summary>
        /// <param name="dbContext"><see cref="DbContext"/> used to query and save changes to a database</param>
        /// <param name="interceptor">Instance of <see cref="IStateInterceptor"/></param>
        public static InterceptorPool WithInterceptor(this DbContext dbContext, IStateInterceptor interceptor)
        {
            return new InterceptorPool(dbContext, interceptor);
        }

        /// <summary>
        /// Injects interceptor implementing <see cref="IStateInterceptor"/> into <see cref="DbContextExtensions.ApplyChanges(DbContext, ITrackable)"/>.
        /// </summary>
        /// <param name="pool">Pool of interceptors.</param>
        /// <param name="interceptor">Instance of <see cref="IStateInterceptor"/></param>
        public static InterceptorPool WithInterceptor(this InterceptorPool pool, IStateInterceptor interceptor)
        {
            return new InterceptorPool(pool, interceptor);
        }

        /// <summary>
        /// Injects interceptor for setting explicitly the state of an entity into <see cref="DbContextExtensions.ApplyChanges(DbContext, ITrackable)"/>.
        /// </summary>
        /// <param name="dbContext"><see cref="DbContext"/> used to query and save changes to a database</param>
        /// <param name="stateSelector">Used for setting state of entity.</param>
        public static InterceptorPool WithStateChangeInterceptor<TEntity>(this DbContext dbContext,
            Func<TEntity, RelationshipType?, EntityState?> stateSelector)
            where TEntity : class, ITrackable
        {
            return WithInterceptor(dbContext, new StateChangeInterceptor<TEntity>(stateSelector));
        }

        /// <summary>
        /// Injects interceptor for setting explicitly the state of an entity into <see cref="DbContextExtensions.ApplyChanges(DbContext, ITrackable)"/>.
        /// </summary>
        /// <param name="pool">Pool of interceptors</param>
        /// <param name="stateSelector">Used for setting state of entity</param>
        public static InterceptorPool WithStateChangeInterceptor<TEntity>(this InterceptorPool pool,
            Func<TEntity, RelationshipType?, EntityState?> stateSelector)
            where TEntity : class, ITrackable
        {
            return WithInterceptor(pool, new StateChangeInterceptor<TEntity>(stateSelector));
        }
    }
}

<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/ClientEntities/Territory.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using TrackableEntities.Client;

namespace TrackableEntities.Tests.Acceptance.ClientEntities
{
    [JsonObject(IsReference = true)]
    public class Territory : EntityBase
    {
        private string _territoryId;
        public string TerritoryId
        {
            get { return _territoryId; }
            set
            {
                if (value == _territoryId) return;
                _territoryId = value;
                NotifyPropertyChanged();
            }
        }

        private string _territoryDescription;
        public string TerritoryDescription
        {
            get { return _territoryDescription; }
            set
            {
                if (value == _territoryDescription) return;
                _territoryDescription = value;
                NotifyPropertyChanged();
            }
        }

        private string _data;
        public string Data
        {
            get { return _data; }
            set
            {
                if (value == _data) return;
                _data = value;
                NotifyPropertyChanged();
            }
        }

        private int _areaId;
        public int AreaId
        {
            get { return _areaId; }
            set
            {
                if (value == _areaId) return;
                _areaId = value;
                NotifyPropertyChanged();
            }
        }

        private Area _area;
        public Area Area
        {
            get { return _area; }
            set
            {
                if (value == _area) return;
                _area = value;
                AreaChangeTracker = _area == null ? null
                    : new ChangeTrackingCollection<Area> { _area };
                NotifyPropertyChanged();
            }
        }
        private ChangeTrackingCollection<Area> AreaChangeTracker { get; set; }

        private ChangeTrackingCollection<Employee> _employees;
        public ChangeTrackingCollection<Employee> Employees
        {
            get { return _employees; }
            set
            {
                if (value != null) value.Parent = this;
                if (Equals(value, _employees)) return;
                _employees = value;
                NotifyPropertyChanged();
            }
        }

        private ChangeTrackingCollection<Customer> _customers;
        public ChangeTrackingCollection<Customer> Customers
        {
            get { return _customers; }
            set
            {
                if (Equals(value, _customers)) return;
                _customers = value;
                NotifyPropertyChanged();
            }
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.ModelFirst/WebApiSample.Client.Entities.Temp/Category.cs<|end_filename|>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace WebApiSample.Client.Entities.Temp
{
    using System;
    using System.Collections.Generic;
    using TrackableEntities.Client;
    
    public partial class Category : EntityBase
    {
        public Category()
        {
            this.Products = new ChangeTrackingCollection<Product>();
        }
        
    	public int CategoryId
    	{ 
    		get { return _CategoryId; }
    		set
    		{
    			if (Equals(value, _CategoryId)) return;
    			_CategoryId = value;
    			NotifyPropertyChanged(() => CategoryId);
    		}
    	}
    	private int _CategoryId;
        
    	public string CategoryName
    	{ 
    		get { return _CategoryName; }
    		set
    		{
    			if (Equals(value, _CategoryName)) return;
    			_CategoryName = value;
    			NotifyPropertyChanged(() => CategoryName);
    		}
    	}
    	private string _CategoryName;
    
    	public ChangeTrackingCollection<Product> Products
    	{
    		get { return _Products; }
    		set
    		{
    			if (Equals(value, _Products)) return;
    			_Products = value;
    			NotifyPropertyChanged(() => Products);
    		}
    	}
    	private ChangeTrackingCollection<Product> _Products;
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.ModelFirst/WebApiSample.Service.Entities/Employee.cs<|end_filename|>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace WebApiSample.Service.Entities
{
    using System;
    using System.Collections.Generic;
    using TrackableEntities;
    
    public partial class Employee : ITrackable, IMergeable
    {
        public Employee()
        {
            this.Territories = new List<Territory>();
        }
    
        public int EmployeeId { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public Nullable<System.DateTime> BirthDate { get; set; }
        public Nullable<System.DateTime> HireDate { get; set; }
        public string City { get; set; }
        public string Country { get; set; }
    
        public ICollection<Territory> Territories { get; set; }
    
        public TrackingState TrackingState { get; set; }
        public ICollection<string> ModifiedProperties { get; set; }
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Source/TrackableEntities.Common/EntityNavigationProperty.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace TrackableEntities.Common
{
    /// <summary>
    /// Common base class for differnt types of entity navigation properties, such as
    /// EntityReferenceProperty and EntityCollectionProperty.
    /// Provides safe cast operations:
    /// <code>
    /// foreach (var navProp in entity.GetNavigationProperties())
    /// {
    ///     // 1-1 and M-1 properties
    ///     foreach (var refProp in navProp.AsReferenceProperty())
    ///         DoSomething(refProp.EntityReference);
    ///
    ///     // 1-M and M-M properties
    ///     foreach (var colProp in navProp.AsCollectionProperty())
    ///         DoSomething(colProp.EntityCollection);
    /// }
    /// </code>
    /// The two inner loops may look unusual but they actually do at most one iteration if the
    /// current 'navProp' is of a requested type. This replaces a less elegant "first-cast-then-check"
    /// contruction.
    /// </summary>
    public abstract class EntityNavigationProperty
    {
        /// <summary>
        /// Property information
        /// </summary>
        public PropertyInfo Property { get; private set; }

        /// <summary>
        /// Casts 'this' to EntityReferenceProperty&lt;TEntity&gt;. Returns an empty enumerable
        /// if 'this' is not a reference property or the entity type is incompatible.
        /// </summary>
        /// <typeparam name="TEntity">Type of entity reference</typeparam>
        public IEnumerable<EntityReferenceProperty<TEntity>> AsReferenceProperty<TEntity>()
            where TEntity : class, ITrackable
        {
            var refProp = this as EntityReferenceProperty;
            if (refProp == null) yield break;

            var entity = refProp.EntityReference as TEntity;
            if (entity == null && !refProp.ValueIsNull) yield break;

            yield return new EntityReferenceProperty<TEntity>(refProp.Property, entity);
        }

        /// <summary>
        /// Shortcut: casts 'this' to EntityReferenceProperty.
        /// </summary>
        public IEnumerable<EntityReferenceProperty> AsReferenceProperty()
        {
            return AsReferenceProperty<ITrackable>();
        }

        /// <summary>
        /// Casts 'this' to EntityCollectionProperty&lt;TEntityCollection&gt;. Returns an empty enumerable
        /// if 'this' is not a collection property or the collection type is incompatible.
        /// </summary>
        /// <typeparam name="TEntityCollection">Type of entity collection</typeparam>
        public IEnumerable<EntityCollectionProperty<TEntityCollection>> AsCollectionProperty<TEntityCollection>()
            where TEntityCollection : class
        {
            var collProp = this as EntityCollectionProperty;
            if (collProp == null) yield break;

            var coll = collProp.EntityCollection as TEntityCollection;
            if (coll == null && !collProp.ValueIsNull) yield break;

            yield return new EntityCollectionProperty<TEntityCollection>(collProp.Property, coll);
        }

        /// <summary>
        /// Shortcut: casts 'this' to EntityCollectionProperty.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<EntityCollectionProperty> AsCollectionProperty()
        {
            return AsCollectionProperty<IEnumerable<ITrackable>>();
        }

        /// <summary>
        /// True if the property value is null
        /// </summary>
        public abstract bool ValueIsNull { get; }

        internal EntityNavigationProperty(PropertyInfo propertyInfo)
        {
            Property = propertyInfo;
        }
    }

    /// <summary>
    /// Represents an entity reference property (1-1 or M-1) of a default type 'ITrackable'.
    /// </summary>
    public class EntityReferenceProperty : EntityNavigationProperty
    {
        /// <summary>
        /// Entity reference value
        /// </summary>
        public ITrackable EntityReference { get; private set; }

        /// <summary>
        /// Creates a new EntityReferenceProperty.
        /// </summary>
        /// <param name="propertyInfo">Property information</param>
        /// <param name="entityReference">Entity reference value</param>
        public EntityReferenceProperty(PropertyInfo propertyInfo, ITrackable entityReference)
            : base(propertyInfo)
        {
            EntityReference = entityReference;
        }

        /// <summary>
        /// True if the property value is null
        /// </summary>
        public override bool ValueIsNull
        {
            get { return EntityReference == null; }
        }
    }

    /// <summary>
    /// Represents an entity reference property (1-1 or M-1) of type 'TEntity'.
    /// </summary>
    /// <typeparam name="TEntity">Type of entity reference</typeparam>
    public class EntityReferenceProperty<TEntity> : EntityReferenceProperty
        where TEntity : ITrackable
    {
        /// <summary>
        /// Entity reference value
        /// </summary>
        new public TEntity EntityReference { get; private set; }

        internal EntityReferenceProperty(PropertyInfo propertyInfo, TEntity entityReference)
            : base(propertyInfo, entityReference)
        {
            EntityReference = entityReference;
        }
    }

    /// <summary>
    /// Represents an entity collection property (1-M or M-M) of a default type 'IEnumerable&lt;ITrackable&gt;'.
    /// </summary>
    public class EntityCollectionProperty : EntityNavigationProperty
    {
        /// <summary>
        /// Entity collection value
        /// </summary>
        public IEnumerable<ITrackable> EntityCollection { get; private set; }

        /// <summary>
        /// Creates a new EntityCollectionProperty.
        /// </summary>
        /// <param name="propertyInfo">Property</param>
        /// <param name="entityCollection">Entity collection value</param>
        public EntityCollectionProperty(PropertyInfo propertyInfo, IEnumerable<ITrackable> entityCollection)
            : base(propertyInfo)
        {
            EntityCollection = entityCollection;
        }

        /// <summary>
        /// True if the property value is null
        /// </summary>
        public override bool ValueIsNull
        {
            get { return EntityCollection == null; }
        }
    }

    /// <summary>
    /// Represents an entity collection property (1-M or M-M) of type 'TEntityCollection'.
    /// </summary>
    /// <typeparam name="TEntityCollection">Type of entity collection</typeparam>
    public class EntityCollectionProperty<TEntityCollection> : EntityCollectionProperty
    {
        /// <summary>
        /// Entity collection value
        /// </summary>
        new public TEntityCollection EntityCollection { get; private set; }

        internal EntityCollectionProperty(PropertyInfo propertyInfo, TEntityCollection entityCollection)
            : base(propertyInfo, entityCollection as IEnumerable<ITrackable>)
        {
            EntityCollection = entityCollection;
        }
    }
}

<|start_filename|>Build/Scripts/TrackableEntities.Client.cmd<|end_filename|>
@echo On
set debug=%1

REM Set Variables:
set config=%Configuration%
if "%Configuration%" == "" (
   set config=Release
)
set version=%PackageVersion%
set name=TrackableEntities.Client
set source=Source\%name%
set logs=Build\Logs\%name%
set output=Build\Output\%name%
set target-portable=portable-net45+wp80+win8+wpa81
set target-sl5=sl5
set target-net45=net45
set src-portable=TrackableEntities.Client
set src-sl5=TrackableEntities.Client.Sl5
set src-net45=TrackableEntities.Client.Net45

REM Restore:
if "%debug%"=="1" pause
Source\.nuget\nuget.exe install "%source%\packages.config" -OutputDirectory Source\packages -NonInteractive
Source\.nuget\nuget.exe install "%source%.Net45\packages.config" -OutputDirectory Source\packages -NonInteractive
Source\.nuget\nuget.exe install "%source%.sl5\packages.config" -OutputDirectory Source\packages -NonInteractive
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit

REM Build:
if "%debug%"=="1" pause
mkdir "%logs%"
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild "%source%\%name%.csproj" /p:Configuration="%config%" /m /v:M /fl /flp:LogFile="%logs%\msbuild.log";Verbosity=Normal /nr:false
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild "%source%.Net45\%name%.Net45.csproj" /p:Configuration="%config%" /m /v:M /fl /flp:LogFile="%logs%\msbuild.Net45.log";Verbosity=Normal /nr:false
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild "%source%.Sl5\%name%.Sl5.csproj" /p:Configuration="%config%" /m /v:M /fl /flp:LogFile="%logs%\msbuild.Sl5.log";Verbosity=Normal /nr:false
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit

REM Portable Copy:
if "%debug%"=="1" pause
mkdir "%output%\lib\%target-portable%"
xcopy "%source%\bin\%config%\%name%.dll" "%output%\lib\%target-portable%\" /y
xcopy "%source%\bin\%config%\%name%.xml" "%output%\lib\%target-portable%\" /y
xcopy "%source%\bin\%config%\%name%.pdb" "%output%\lib\%target-portable%\" /y

mkdir "%output%\src\%src-portable%\Properties"
xcopy "Source\AssemblyVersion.cs" "%output%\src\%src-portable%\Properties\" /y
xcopy "%source%\Properties\AssemblyInfo.cs" "%output%\src\%src-portable%\Properties\" /y
xcopy "%source%\*.cs" "%output%\src\%src-portable%\" /y
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit

REM Portable-SL5 Copy:
if "%debug%"=="1" pause
mkdir "%output%\lib\%target-sl5%"
xcopy "%source%\bin\%config%\%name%.dll" "%output%\lib\%target-sl5%\" /y
xcopy "%source%\bin\%config%\%name%.xml" "%output%\lib\%target-sl5%\" /y
xcopy "%source%\bin\%config%\%name%.pdb" "%output%\lib\%target-sl5%\" /y

mkdir "%output%\src\%src-sl5%\Properties"
xcopy "Source\AssemblyVersion.cs" "%output%\src\%src-sl5%\Properties\" /y
xcopy "%source%\Properties\AssemblyInfo.cs" "%output%\src\%src-sl5%\Properties\" /y
xcopy "%source%\*.cs" "%output%\src\%src-sl5%\" /y
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit

REM Net45 Copy:
if "%debug%"=="1" pause
mkdir "%output%\lib\%target-net45%"
xcopy "%source%.Net45\bin\%config%\%name%.dll" "%output%\lib\%target-net45%\" /y
xcopy "%source%.Net45\bin\%config%\%name%.xml" "%output%\lib\%target-net45%\" /y
xcopy "%source%.Net45\bin\%config%\%name%.pdb" "%output%\lib\%target-net45%\" /y

mkdir "%output%\src\%src-net45%\Properties"
xcopy "Source\AssemblyVersion.cs" "%output%\src\%src-net45%\Properties\" /y
xcopy "%source%\Properties\AssemblyInfo.cs" "%output%\src\%src-net45%\Properties\" /y
xcopy "%source%\*.cs" "%output%\src\%src-net45%\" /y
del "%output%\src\%src-net45%\EntityBasePortable.cs"
xcopy "%source%.Net45\*.cs" "%output%\src\%src-net45%\" /y
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit

REM Package:
if "%debug%"=="1" pause
xcopy "%source%\%name%.nuspec" "%output%\" /y
Source\.nuget\nuget.exe pack "%output%\%name%.nuspec" -symbols -o "%output%" -p PackageVersion="%version%"
if "%debug%"=="1" pause
if not "%errorlevel%"=="0" exit


<|start_filename|>Source/Tests/TrackableEntities.EF.5.Tests/Helpers/DbContextHelper.cs<|end_filename|>
﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
#if EF_6
using System.Data.Entity.Core;
using System.Data.Entity.Core.Objects;
#else
using System.Data.Objects;
#endif
using System.Data.Entity.Infrastructure;
using System.Linq;
using TrackableEntities.Common;

namespace TrackableEntities.EF.Tests
{
    internal static class DbContextHelper
    {
        // Recursively get entity states
        public static IEnumerable<EntityState> GetEntityStates(this DbContext context,
            ITrackable item, EntityState? entityState = null,
            ObjectVisitationHelper visitationHelper = null)
        {
            // Prevent endless recursion
            ObjectVisitationHelper.EnsureCreated(ref visitationHelper);
            if (!visitationHelper.TryVisit(item)) yield break;

            foreach (var colProp in item.GetNavigationProperties().OfCollectionType())
            {
                foreach (ITrackable child in colProp.EntityCollection)
                {
                    foreach (var state in context.GetEntityStates(child, visitationHelper: visitationHelper))
                    {
                        if (entityState == null || state == entityState)
                            yield return state;
                    }
                }
            }
            yield return context.Entry(item).State;
        }

        // Returns true if target entity has been added to relationship with source entity
        public static bool RelatedItemHasBeenAdded(this DbContext context,
            object source, object target)
        {
            var addedRels = context.GetAddedRelationships();
            bool itemAdded = addedRels
                .Any(r => ReferenceEquals(r.Item1, source)
                    && ReferenceEquals(r.Item2, target));
            return itemAdded;
        }

        // Returns true if target entity has been removed from relationship with source entity
        public static bool RelatedItemHasBeenRemoved(this DbContext context,
            object source, object target)
        {
            var deletedRels = context.GetDeletedRelationships();
            bool itemRemoved = deletedRels
                .Any(r => ReferenceEquals(r.Item1, source)
                    && ReferenceEquals(r.Item2, target));
            return itemRemoved;
        }

        // Returns tuples with ends for added relationships
        public static IEnumerable<Tuple<object, object>> GetAddedRelationships
            (this DbContext context)
        {
            return GetRelationships(context, EntityState.Added, (e, i) => e.CurrentValues[i]);
        }

        // Returns tuples with ends for added relationships
        public static IEnumerable<Tuple<object, object>> GetDeletedRelationships
            (this DbContext context)
        {
            return GetRelationships(context, EntityState.Deleted, (e, i) => e.OriginalValues[i]);
        }

        private static IEnumerable<Tuple<object, object>> GetRelationships(
            this DbContext context,
            EntityState relationshipState,
            Func<ObjectStateEntry, int, object> getValue)
        {
            context.ChangeTracker.DetectChanges();
            var objectContext = ((IObjectContextAdapter)context).ObjectContext;

            return objectContext.ObjectStateManager
                .GetObjectStateEntries(relationshipState)
                .Where(e => e.IsRelationship)
                .Select(
                    e => Tuple.Create(
                        objectContext.GetObjectByKey((EntityKey)getValue(e, 0)),
                        objectContext.GetObjectByKey((EntityKey)getValue(e, 1))));
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.ModelFirst/WebApiSample.Client.Entities.Temp/Territory.cs<|end_filename|>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace WebApiSample.Client.Entities.Temp
{
    using System;
    using System.Collections.Generic;
    using TrackableEntities.Client;
    
    public partial class Territory : EntityBase
    {
        public Territory()
        {
            this.Employees = new ChangeTrackingCollection<Employee>();
        }
        
    	public string TerritoryId
    	{ 
    		get { return _TerritoryId; }
    		set
    		{
    			if (Equals(value, _TerritoryId)) return;
    			_TerritoryId = value;
    			NotifyPropertyChanged(() => TerritoryId);
    		}
    	}
    	private string _TerritoryId;
        
    	public string TerritoryDescription
    	{ 
    		get { return _TerritoryDescription; }
    		set
    		{
    			if (Equals(value, _TerritoryDescription)) return;
    			_TerritoryDescription = value;
    			NotifyPropertyChanged(() => TerritoryDescription);
    		}
    	}
    	private string _TerritoryDescription;
    
    	public ChangeTrackingCollection<Employee> Employees
    	{
    		get { return _Employees; }
    		set
    		{
    			if (Equals(value, _Employees)) return;
    			_Employees = value;
    			NotifyPropertyChanged(() => Employees);
    		}
    	}
    	private ChangeTrackingCollection<Employee> _Employees;
    }
}


<|start_filename|>Source/Tests/TrackableEntities.EF.5.Tests/StateInterceptorTests.cs<|end_filename|>
﻿#if EF_6
using System.Data.Entity;
#else
using System.Data;
#endif
using System.Collections.Generic;
using System.Linq;
using TrackableEntities.EF.Tests;
using TrackableEntities.EF.Tests.Mocks;
using TrackableEntities.EF.Tests.NorthwindModels;
using Xunit;

// ReSharper disable CheckNamespace
#if EF_6
namespace TrackableEntities.EF6.Tests
#else
namespace TrackableEntities.EF5.Tests
#endif
{
    public class StateInterceptorTests
    {
        // ReSharper disable once InconsistentNaming
        private const CreateDbOptions CreateNorthwindDbOptions = CreateDbOptions.DropCreateDatabaseIfModelChanges;

        [Fact]
        public void Interceptor_Should_Change_Entities_States()
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var nw = new MockNorthwind();
            int[] ids = {1, 2, 3};
            var products = nw.Products.Where(e => ids.Contains(e.ProductId)).ToList();
            products.ForEach(e => e.TrackingState = TrackingState.Modified);
            var cache = new Dictionary<int, EntityState>
            {
                { 1, EntityState.Added },
                { 2, EntityState.Deleted },
                { 3, EntityState.Unchanged },
            };

            // Act
            context
                .WithInterceptor(new ProductCacheStateInterceptor(cache))
                .ApplyChanges(products);

            // Assert
            Assert.Equal(EntityState.Added, context.Entry(products[0]).State);
            Assert.Equal(EntityState.Deleted, context.Entry(products[1]).State);
            Assert.Equal(EntityState.Unchanged, context.Entry(products[2]).State);
        }

        [Fact]
        public void Interceptor_Should_Not_Change_Entities_States()
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var nw = new MockNorthwind();
            int[] ids = { 4, 5, 6 };
            var products = nw.Products.Where(e => ids.Contains(e.ProductId)).ToList();
            products.ForEach(e => e.TrackingState = TrackingState.Modified);
            var cache = new Dictionary<int, EntityState>
            {
                { 1, EntityState.Added },
                { 2, EntityState.Deleted },
                { 3, EntityState.Unchanged },
            };

            // Act
            context
                .WithInterceptor(new ProductCacheStateInterceptor(cache))
                .ApplyChanges(products);

            // Assert
            Assert.Equal(EntityState.Modified, context.Entry(products[0]).State);
            Assert.Equal(EntityState.Modified, context.Entry(products[1]).State);
            Assert.Equal(EntityState.Modified, context.Entry(products[2]).State);
        }

        #region IStateInterceptor Implementations

        // Look up entity states in a products cache
        private class ProductCacheStateInterceptor : IStateInterceptor
        {
            private readonly Dictionary<int, EntityState> _cache;

            public ProductCacheStateInterceptor(Dictionary<int, EntityState> cache)
            {
                _cache = cache;
            }
             
            public EntityState? GetEntityState(ITrackable item, RelationshipType? relationshipType)
            {
                var product = item as Product;
                if (product == null) return null;

                EntityState state;
                if (_cache.TryGetValue(product.ProductId, out state))
                    return state;
                return null;
            }
        }

        #endregion
    }
}


<|start_filename|>Samples/VS2012/WcfSample/WcfSample.Client.Entities/Models/Employee.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using TrackableEntities;
using TrackableEntities.Client;

namespace WcfSample.Client.Entities.Models
{
    [JsonObject(IsReference = true)]
    [DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
    public partial class Employee : ModelBase<Employee>, IEquatable<Employee>, ITrackable
    {
		public Employee()
		{
			this.Territories = new ChangeTrackingCollection<Territory>();
		}

		[DataMember]
		public int EmployeeId
		{ 
			get { return _EmployeeId; }
			set
			{
				if (Equals(value, _EmployeeId)) return;
				_EmployeeId = value;
				NotifyPropertyChanged(m => m.EmployeeId);
			}
		}
		private int _EmployeeId;

		[DataMember]
		public string LastName
		{ 
			get { return _LastName; }
			set
			{
				if (Equals(value, _LastName)) return;
				_LastName = value;
				NotifyPropertyChanged(m => m.LastName);
			}
		}
		private string _LastName;

		[DataMember]
		public string FirstName
		{ 
			get { return _FirstName; }
			set
			{
				if (Equals(value, _FirstName)) return;
				_FirstName = value;
				NotifyPropertyChanged(m => m.FirstName);
			}
		}
		private string _FirstName;

		[DataMember]
		public Nullable<System.DateTime> BirthDate
		{ 
			get { return _BirthDate; }
			set
			{
				if (Equals(value, _BirthDate)) return;
				_BirthDate = value;
				NotifyPropertyChanged(m => m.BirthDate);
			}
		}
		private Nullable<System.DateTime> _BirthDate;

		[DataMember]
		public Nullable<System.DateTime> HireDate
		{ 
			get { return _HireDate; }
			set
			{
				if (Equals(value, _HireDate)) return;
				_HireDate = value;
				NotifyPropertyChanged(m => m.HireDate);
			}
		}
		private Nullable<System.DateTime> _HireDate;

		[DataMember]
		public string City
		{ 
			get { return _City; }
			set
			{
				if (Equals(value, _City)) return;
				_City = value;
				NotifyPropertyChanged(m => m.City);
			}
		}
		private string _City;

		[DataMember]
		public string Country
		{ 
			get { return _Country; }
			set
			{
				if (Equals(value, _Country)) return;
				_Country = value;
				NotifyPropertyChanged(m => m.Country);
			}
		}
		private string _Country;

		[DataMember]
		public ChangeTrackingCollection<Territory> Territories
		{
			get { return _Territories; }
			set
			{
				if (value != null) value.Parent = this;
				if (Equals(value, _Territories)) return;
				_Territories = value;
				NotifyPropertyChanged(m => m.Territories);
			}
		}
		private ChangeTrackingCollection<Territory> _Territories;

        #region Change Tracking

		[DataMember]
		public TrackingState TrackingState { get; set; }

		[DataMember]
		public ICollection<string> ModifiedProperties { get; set; }

		[JsonProperty, DataMember]
		private Guid EntityIdentifier { get; set; }

		#pragma warning disable 414

		[JsonProperty, DataMember]
		private Guid _entityIdentity = default(Guid);

		#pragma warning restore 414

		bool IEquatable<Employee>.Equals(Employee other)
		{
			if (EntityIdentifier != default(Guid))
				return EntityIdentifier == other.EntityIdentifier;
			return false;
		}
        #endregion
	}
}


<|start_filename|>Source/TrackableEntities.EF.5/InterceptorPool.cs<|end_filename|>
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;

#if EF_6
namespace TrackableEntities.EF6
#else
namespace TrackableEntities.EF5
#endif
{
    /// <summary>
    /// Pool of interceptors.
    /// </summary>
    public class InterceptorPool
    {
        internal DbContext DbContext { get; private set; }
        internal IEnumerable<IStateInterceptor> Interceptors { get; private set; }

        internal InterceptorPool(DbContext dbContext, IStateInterceptor interceptor)
            : this(dbContext, Enumerable.Empty<IStateInterceptor>(), interceptor)
        { }

        internal InterceptorPool(InterceptorPool previousPool, IStateInterceptor interceptor)
            : this(previousPool.DbContext, previousPool.Interceptors, interceptor)
        { }

        private InterceptorPool(DbContext dbContext, IEnumerable<IStateInterceptor> previousInterceptors, IStateInterceptor interceptor)
        {
            DbContext = dbContext;
            Interceptors = previousInterceptors.Union(Enumerable.Repeat(interceptor, 1));
        }
    }
}

<|start_filename|>Source/Tests/TrackableEntities.EF.5.Tests/NorthwindModels/CustomerSetting.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TrackableEntities.EF.Tests.NorthwindModels
{
    public partial class CustomerSetting : ITrackable
    {
        [Key]
        public string CustomerId { get; set; }
        public string Setting { get; set; }

        [ForeignKey("CustomerId")]
        public Customer Customer { get; set; }

        [NotMapped]
        public TrackingState TrackingState { get; set; }
        [NotMapped]
        public ICollection<string> ModifiedProperties { get; set; }
    }
}


<|start_filename|>Extensions/Common/Wizards/EntitiesSelectionWizard/EntitiesSelectionDialog.Designer.cs<|end_filename|>
﻿namespace EntitiesSelectionWizard
{
    partial class EntitiesSelectionDialog
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            System.Windows.Forms.ListViewItem listViewItem1 = new System.Windows.Forms.ListViewItem("Service", "server-icon.png");
            System.Windows.Forms.ListViewItem listViewItem2 = new System.Windows.Forms.ListViewItem("Client", "client-icon.png");
            System.Windows.Forms.ListViewItem listViewItem3 = new System.Windows.Forms.ListViewItem("Shared", "shared-icon.png");
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EntitiesSelectionDialog));
            System.Windows.Forms.ListViewItem listViewItem4 = new System.Windows.Forms.ListViewItem(".Net 4.5", "dotnet-icon.png");
            System.Windows.Forms.ListViewItem listViewItem5 = new System.Windows.Forms.ListViewItem("Portable", "portable-icon.png");
            System.Windows.Forms.ListViewItem listViewItem6 = new System.Windows.Forms.ListViewItem("Client / Service", "client-icon.png");
            System.Windows.Forms.ListViewItem listViewItem7 = new System.Windows.Forms.ListViewItem("Shared", "shared-icon.png");
            this.descriptionLabel = new System.Windows.Forms.Label();
            this.buttonsPanel = new System.Windows.Forms.Panel();
            this.finishButton = new System.Windows.Forms.Button();
            this.nextButton = new System.Windows.Forms.Button();
            this.previousButton = new System.Windows.Forms.Button();
            this.cancelButton = new System.Windows.Forms.Button();
            this.serviceClientSharedListView = new System.Windows.Forms.ListView();
            this.wizardImageList = new System.Windows.Forms.ImageList(this.components);
            this.portableDotNetListView = new System.Windows.Forms.ListView();
            this.clientServiceListView = new System.Windows.Forms.ListView();
            this.buttonsPanel.SuspendLayout();
            this.SuspendLayout();
            // 
            // descriptionLabel
            // 
            this.descriptionLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.descriptionLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.descriptionLabel.Font = new System.Drawing.Font("Segoe UI", 9F);
            this.descriptionLabel.Location = new System.Drawing.Point(18, 110);
            this.descriptionLabel.Name = "descriptionLabel";
            this.descriptionLabel.Size = new System.Drawing.Size(362, 63);
            this.descriptionLabel.TabIndex = 1;
            this.descriptionLabel.Text = "Description";
            // 
            // buttonsPanel
            // 
            this.buttonsPanel.Controls.Add(this.finishButton);
            this.buttonsPanel.Controls.Add(this.nextButton);
            this.buttonsPanel.Controls.Add(this.previousButton);
            this.buttonsPanel.Controls.Add(this.cancelButton);
            this.buttonsPanel.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.buttonsPanel.Location = new System.Drawing.Point(0, 173);
            this.buttonsPanel.Name = "buttonsPanel";
            this.buttonsPanel.Size = new System.Drawing.Size(399, 47);
            this.buttonsPanel.TabIndex = 19;
            // 
            // finishButton
            // 
            this.finishButton.Enabled = false;
            this.finishButton.Location = new System.Drawing.Point(203, 10);
            this.finishButton.Name = "finishButton";
            this.finishButton.Size = new System.Drawing.Size(87, 27);
            this.finishButton.TabIndex = 19;
            this.finishButton.TabStop = false;
            this.finishButton.Text = "&Finish";
            this.finishButton.UseVisualStyleBackColor = true;
            this.finishButton.Click += new System.EventHandler(this.finishButton_Click);
            // 
            // nextButton
            // 
            this.nextButton.Location = new System.Drawing.Point(110, 10);
            this.nextButton.Name = "nextButton";
            this.nextButton.Size = new System.Drawing.Size(87, 27);
            this.nextButton.TabIndex = 18;
            this.nextButton.TabStop = false;
            this.nextButton.Text = "&Next >";
            this.nextButton.UseVisualStyleBackColor = true;
            this.nextButton.Click += new System.EventHandler(this.nextButton_Click);
            // 
            // previousButton
            // 
            this.previousButton.Enabled = false;
            this.previousButton.Location = new System.Drawing.Point(17, 10);
            this.previousButton.Name = "previousButton";
            this.previousButton.Size = new System.Drawing.Size(87, 27);
            this.previousButton.TabIndex = 16;
            this.previousButton.TabStop = false;
            this.previousButton.Text = "< &Previous";
            this.previousButton.UseVisualStyleBackColor = true;
            this.previousButton.Click += new System.EventHandler(this.previousButton_Click);
            // 
            // cancelButton
            // 
            this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
            this.cancelButton.Location = new System.Drawing.Point(296, 10);
            this.cancelButton.Name = "cancelButton";
            this.cancelButton.Size = new System.Drawing.Size(87, 27);
            this.cancelButton.TabIndex = 17;
            this.cancelButton.TabStop = false;
            this.cancelButton.Text = "Cancel";
            this.cancelButton.UseVisualStyleBackColor = true;
            this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
            // 
            // serviceClientSharedListView
            // 
            this.serviceClientSharedListView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            listViewItem2.Checked = true;
            listViewItem2.StateImageIndex = 1;
            this.serviceClientSharedListView.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
            listViewItem1,
            listViewItem2,
            listViewItem3});
            this.serviceClientSharedListView.LargeImageList = this.wizardImageList;
            this.serviceClientSharedListView.Location = new System.Drawing.Point(18, 12);
            this.serviceClientSharedListView.MultiSelect = false;
            this.serviceClientSharedListView.Name = "serviceClientSharedListView";
            this.serviceClientSharedListView.Size = new System.Drawing.Size(362, 80);
            this.serviceClientSharedListView.TabIndex = 20;
            this.serviceClientSharedListView.UseCompatibleStateImageBehavior = false;
            this.serviceClientSharedListView.SelectedIndexChanged += new System.EventHandler(this.serviceClientSharedListView_SelectedIndexChanged);
            // 
            // wizardImageList
            // 
            this.wizardImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("wizardImageList.ImageStream")));
            this.wizardImageList.TransparentColor = System.Drawing.Color.Transparent;
            this.wizardImageList.Images.SetKeyName(0, "client-icon.png");
            this.wizardImageList.Images.SetKeyName(1, "server-icon.png");
            this.wizardImageList.Images.SetKeyName(2, "shared-icon.png");
            this.wizardImageList.Images.SetKeyName(3, "portable-icon.png");
            this.wizardImageList.Images.SetKeyName(4, "dotnet-icon.png");
            // 
            // portableDotNetListView
            // 
            this.portableDotNetListView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.portableDotNetListView.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
            listViewItem4,
            listViewItem5});
            this.portableDotNetListView.LargeImageList = this.wizardImageList;
            this.portableDotNetListView.Location = new System.Drawing.Point(18, 12);
            this.portableDotNetListView.MultiSelect = false;
            this.portableDotNetListView.Name = "portableDotNetListView";
            this.portableDotNetListView.Size = new System.Drawing.Size(362, 80);
            this.portableDotNetListView.TabIndex = 21;
            this.portableDotNetListView.UseCompatibleStateImageBehavior = false;
            this.portableDotNetListView.Visible = false;
            this.portableDotNetListView.SelectedIndexChanged += new System.EventHandler(this.portableDotNetListView_SelectedIndexChanged);
            // 
            // clientServiceListView
            // 
            this.clientServiceListView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            listViewItem6.Checked = true;
            listViewItem6.StateImageIndex = 1;
            this.clientServiceListView.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
            listViewItem6,
            listViewItem7});
            this.clientServiceListView.LargeImageList = this.wizardImageList;
            this.clientServiceListView.Location = new System.Drawing.Point(18, 12);
            this.clientServiceListView.MultiSelect = false;
            this.clientServiceListView.Name = "clientServiceListView";
            this.clientServiceListView.Size = new System.Drawing.Size(362, 80);
            this.clientServiceListView.TabIndex = 22;
            this.clientServiceListView.UseCompatibleStateImageBehavior = false;
            this.clientServiceListView.SelectedIndexChanged += new System.EventHandler(this.clientServiceListView_SelectedIndexChanged);
            // 
            // EntitiesSelectionDialog
            // 
            this.AcceptButton = this.previousButton;
            this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.CancelButton = this.cancelButton;
            this.ClientSize = new System.Drawing.Size(399, 220);
            this.Controls.Add(this.clientServiceListView);
            this.Controls.Add(this.serviceClientSharedListView);
            this.Controls.Add(this.portableDotNetListView);
            this.Controls.Add(this.buttonsPanel);
            this.Controls.Add(this.descriptionLabel);
            this.Font = new System.Drawing.Font("Segoe UI", 9F);
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.MinimumSize = new System.Drawing.Size(415, 259);
            this.Name = "EntitiesSelectionDialog";
            this.ShowIcon = false;
            this.ShowInTaskbar = false;
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "Entities Selection";
            this.buttonsPanel.ResumeLayout(false);
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.Label descriptionLabel;
        private System.Windows.Forms.Panel buttonsPanel;
        private System.Windows.Forms.Button previousButton;
        private System.Windows.Forms.Button cancelButton;
        private System.Windows.Forms.Button nextButton;
        private System.Windows.Forms.Button finishButton;
        private System.Windows.Forms.ListView serviceClientSharedListView;
        private System.Windows.Forms.ImageList wizardImageList;
        private System.Windows.Forms.ListView portableDotNetListView;
        private System.Windows.Forms.ListView clientServiceListView;
    }
}

<|start_filename|>Samples/VS2013/WebApiSample.ModelFirst/WebApiSample.WebApi/Controllers/CustomerController.cs<|end_filename|>
﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using TrackableEntities;
using TrackableEntities.EF6;
using TrackableEntities.Common;
using WebApiSample.Service.Entities;

namespace WebApiSample.Service.WebApi.Controllers
{
    public class CustomerController : ApiController
    {
        private readonly NorthwindSlimEntities _dbContext = new NorthwindSlimEntities();

        // GET api/Customer
        [ResponseType(typeof(IEnumerable<Customer>))]
        public async Task<IHttpActionResult> GetCustomers()
        {
	        IEnumerable<Customer> customers = await _dbContext.Customers
				.Include(c => c.CustomerSetting)
				.ToListAsync();
	
            return Ok(customers);
        }

        // GET api/Customer/5
        [ResponseType(typeof(Customer))]
        public async Task<IHttpActionResult> GetCustomer(string id)
        {
	        Customer customer = await _dbContext.Customers
				.Include(c => c.CustomerSetting)
				.SingleOrDefaultAsync(c => c.CustomerId == id);
	
            if (customer == null)
            {
                return NotFound();
            }

            return Ok(customer);
        }

        // POST api/Customer
        [ResponseType(typeof(Customer))]
        public async Task<IHttpActionResult> PostCustomer(Customer customer)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            customer.TrackingState = TrackingState.Added;
            _dbContext.ApplyChanges(customer);


            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateException)
            {
                if (_dbContext.Customers.Any(c => c.CustomerId == customer.CustomerId))
                {
                    return Conflict();
                }
                throw;
            }

            await _dbContext.LoadRelatedEntitiesAsync(customer);
            customer.AcceptChanges();
            return CreatedAtRoute("DefaultApi", new { id = customer.CustomerId }, customer);
        }

        // PUT api/Customer
        [ResponseType(typeof(Customer))]
        public async Task<IHttpActionResult> PutCustomer(Customer customer)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            _dbContext.ApplyChanges(customer);

            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!_dbContext.Customers.Any(c => c.CustomerId == customer.CustomerId))
                {
                    return Conflict();
                }
                throw;
            }

			await _dbContext.LoadRelatedEntitiesAsync(customer);
			customer.AcceptChanges();
	        return Ok(customer);
        }

        // DELETE api/Customer/5
        public async Task<IHttpActionResult> DeleteCustomer(string id)
        {
			Customer customer = await _dbContext.Customers
				.SingleOrDefaultAsync(c => c.CustomerId == id);
			if (customer == null)
            {
                return Ok();
            }

			customer.TrackingState = TrackingState.Deleted;
			_dbContext.ApplyChanges(customer);

            try
            {
	            await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!_dbContext.Customers.Any(c => c.CustomerId == customer.CustomerId))
                {
                    return Conflict();
                }
                throw;
            }

            return Ok();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _dbContext.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}

<|start_filename|>Source/Tests/TrackableEntities.Client.Tests.Extensions/ChangeTrackingExtensionsTests.cs<|end_filename|>
﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using TrackableEntities.Client.Tests.Entities.FamilyModels;
using TrackableEntities.Client.Tests.Entities.Mocks;
using TrackableEntities.Client.Tests.Entities.NorthwindModels;
using TrackableEntities.Common;
using Xunit;

namespace TrackableEntities.Client.Tests.Extensions
{
    public class ChangeTrackingExtensionsTests
    {
        #region MergeChanges Tests

        #region MergeChanges: Single Entity
        
        [Fact]
        public void MergeChanges_Should_Set_Properties_For_Modified_Order_With_Updated_Customer()
        {
            // Arrange
            var database = new MockNorthwind();
            var origOrder = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(origOrder);
            origOrder.CustomerId = "ALFKI";
            var updatedOrder = UpdateOrders(database, origOrder)[0];

            // Act
            changeTracker.MergeChanges(updatedOrder);

            // Assert
            Assert.Equal(updatedOrder.CustomerId, origOrder.CustomerId);
            Assert.Equal(updatedOrder.Customer.CustomerId, origOrder.Customer.CustomerId);
            Assert.Equal(updatedOrder.OrderDate, origOrder.OrderDate);
        }

        [Fact]
        public void MergeChanges_Should_Set_TrackingState_To_Unchanged_For_Modified_Order_With_Updated_Customer()
        {
            // Arrange
            var database = new MockNorthwind();
            var origOrder = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(origOrder);
            origOrder.CustomerId = "ALFKI";
            TrackingState origTrackingState = origOrder.TrackingState;
            var updatedOrder = UpdateOrders(database, origOrder)[0];

            // Act
            changeTracker.MergeChanges(updatedOrder);

            // Assert
            Assert.Equal(TrackingState.Modified, origTrackingState);
            Assert.Equal(TrackingState.Unchanged, origOrder.TrackingState);
        }

        [Fact]
        public void MergeChanges_Should_Set_ModifiedProperties_To_Null_For_Modified_Order_With_Updated_Customer()
        {
            // Arrange
            var database = new MockNorthwind();
            var origOrder = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(origOrder);
            origOrder.CustomerId = "ALFKI";
            var origModifiedProps = origOrder.ModifiedProperties;
            var updatedOrder = UpdateOrders(database, origOrder)[0];

            // Act
            changeTracker.MergeChanges(updatedOrder);

            // Assert
            Assert.Contains("CustomerId", origModifiedProps);
            Assert.Null(origOrder.ModifiedProperties);
        }

        [Fact]
        public void MergeChanges_Should_Set_ChangeTracker_For_Modified_Order_With_Updated_Customer()
        {
            // Arrange
            var database = new MockNorthwind();
            var origOrder = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(origOrder);
            origOrder.CustomerId = "ALFKI";
            var updatedOrder = UpdateOrders(database, origOrder)[0];

            // Act
            changeTracker.MergeChanges(updatedOrder);
            TrackingState origTrackingState = origOrder.Customer.TrackingState;
            origOrder.Customer.CustomerName = "xxx";

            // Assert
            Assert.Equal(TrackingState.Unchanged, origTrackingState);
            Assert.Equal(TrackingState.Modified, origOrder.Customer.TrackingState);
            Assert.Contains("CustomerName", origOrder.Customer.ModifiedProperties);
        }

        [Fact]
        public void MergeChanges_Should_Set_Properties_For_Added_Order_With_Null_Customer()
        {
            // Arrange
            var database = new MockNorthwind();
            var origOrder = new Order
            {
                OrderDate = DateTime.Parse("1996-07-04"),
                CustomerId = "ALFKI"
            };
            var changeTracker = new ChangeTrackingCollection<Order>(true) {origOrder};
            TrackingState origTrackingState = origOrder.TrackingState;
            var addedOrder = AddOrders(database, origOrder)[0];

            // Act
            changeTracker.MergeChanges(addedOrder);

            // Assert
            Assert.Equal(TrackingState.Added, origTrackingState);
            Assert.Equal(TrackingState.Unchanged, origOrder.TrackingState);
        }

        [Fact]
        public void MergeChanges_Should_Set_TrackingState_To_Unchanged_For_Added_Order_With_Null_Customer()
        {
            // Arrange
            var database = new MockNorthwind();
            var origOrder = new PriorityOrder
            {
                PriorityPlan = "Silver",
                OrderDate = DateTime.Parse("1996-07-04"),
                CustomerId = "ALFKI"
            };
            var changeTracker = new ChangeTrackingCollection<Order>(true) { origOrder };
            var addedOrder = AddOrders(database, origOrder)[0];

            // Act
            changeTracker.MergeChanges(addedOrder);

            // Assert
            Assert.Equal(addedOrder.CustomerId, origOrder.CustomerId);
            Assert.Equal(addedOrder.Customer.CustomerId, origOrder.Customer.CustomerId);
            Assert.Equal(addedOrder.OrderDate, origOrder.OrderDate);
        }

        [Fact]
        public void MergeChanges_Should_Set_ChangeTracker_For_Added_Order_With_Null_Customer()
        {
            // Arrange
            var database = new MockNorthwind();
            var origOrder = new Order
            {
                OrderDate = DateTime.Parse("1996-07-04"),
                CustomerId = "ALFKI"
            };
            var changeTracker = new ChangeTrackingCollection<Order>(true) { origOrder };
            var addedOrder = AddOrders(database, origOrder)[0];

            // Act
            changeTracker.MergeChanges(addedOrder);
            TrackingState origTrackingState = origOrder.Customer.TrackingState;
            origOrder.Customer.CustomerName = "xxx";

            // Assert
            Assert.Equal(TrackingState.Unchanged, origTrackingState);
            Assert.Equal(TrackingState.Modified, origOrder.Customer.TrackingState);
            Assert.Contains("CustomerName", origOrder.Customer.ModifiedProperties);
        }

        #endregion

        #region MergeChanges: Multiple Entities

        [Fact]
        public void MergeChanges_Should_Set_Properties_For_Multiple_Modified_Orders_With_Updated_Customer()
        {
            // Arrange
            var database = new MockNorthwind();
            var origOrder1 = database.Orders[0];
            var origOrder2 = database.Orders[1];
            var changeTracker = new ChangeTrackingCollection<Order>(origOrder1, origOrder2);
            origOrder1.CustomerId = "ALFKI";
            origOrder2.CustomerId = "ANATR";
            var updatedOrders = UpdateOrders(database, origOrder1, origOrder2);

            // Act
            changeTracker.MergeChanges(updatedOrders.ToArray());

            // Assert
            Assert.Equal(updatedOrders[0].CustomerId, origOrder1.CustomerId);
            Assert.Equal(updatedOrders[0].Customer.CustomerId, origOrder1.Customer.CustomerId);
            Assert.Equal(updatedOrders[0].OrderDate, origOrder1.OrderDate);
            Assert.Equal(updatedOrders[1].CustomerId, origOrder2.CustomerId);
            Assert.Equal(updatedOrders[1].Customer.CustomerId, origOrder2.Customer.CustomerId);
            Assert.Equal(updatedOrders[1].OrderDate, origOrder2.OrderDate);
        }

        #endregion

        #region MergeChanges: One-to-Many

        [Fact]
        public void MergeChanges_Should_Merge_Updates_For_Unchanged_Order_With_Changed_OrderDetails()
        {
            // Arrange
            var database = new MockNorthwind();
            var origOrder = database.Orders[0];
            var product = database.Products.Single(p => p.ProductId == 14);
            origOrder.OrderDetails.Add(new OrderDetail { ProductId = 14, OrderId = 10249, Quantity = 9, UnitPrice = 18.6000M, Product = product });
            var unchangedDetail = origOrder.OrderDetails[0];
            var modifiedDetail = origOrder.OrderDetails[1];
            var deletedDetail = origOrder.OrderDetails[3];
            var changeTracker = new ChangeTrackingCollection<Order>(origOrder);
            origOrder.OrderDetails[1].Product.ProductName = "xxx";
            origOrder.OrderDetails[2].Quantity++;
            origOrder.OrderDetails[2].ProductId = 1;
            var newUnitPrice = origOrder.OrderDetails[2].UnitPrice + 1;
            origOrder.OrderDetails.RemoveAt(3);
            var addedDetail = new OrderDetail {ProductId = 51, OrderId = 10249, Quantity = 40, UnitPrice = 42.4000M};
            origOrder.OrderDetails.Add(addedDetail);

            var changes = changeTracker.GetChanges();
            var updatedOrder = UpdateOrdersWithDetails(database, changes)[0];

            // Act
            changeTracker.MergeChanges(updatedOrder);

            // Assert
            Assert.Contains(unchangedDetail, origOrder.OrderDetails); // Unchanged present
            Assert.Equal("xxx", origOrder.OrderDetails[1].Product.ProductName); // Prod name updated
            Assert.Equal(updatedOrder.OrderDetails[1].ProductId, origOrder.OrderDetails[2].Product.ProductId); // Changed Product set
            Assert.Equal(newUnitPrice, origOrder.OrderDetails[2].UnitPrice); // Db-generated value set
            Assert.Equal(updatedOrder.OrderDetails[2].Product.ProductId, origOrder.OrderDetails[3].Product.ProductId); // Added detail Product set
            Assert.True(origOrder.OrderDetails.All(d => d.TrackingState == TrackingState.Unchanged)); // Details unchanged
            Assert.Same(addedDetail, origOrder.OrderDetails.Single(d => d.ProductId == 51)); // Ref equality
            Assert.Same(modifiedDetail, origOrder.OrderDetails.Single(d => d.ProductId == 42)); // Ref equality
            Assert.DoesNotContain(deletedDetail, origOrder.OrderDetails); // Detail deleted
            ICollection cachedDeletes = ((ITrackingCollection)origOrder.OrderDetails).CachedDeletes;
            Assert.Empty(cachedDeletes); // Cached deletes have been removed
        }

        #endregion

        #region MergeChanges: Many-to-One

        [Fact]
        public void MergeChanges_Should_Set_Modified_Order_With_Unchanged_Customer()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var date = order.OrderDate = order.OrderDate.AddDays(1);
            var origState = order.TrackingState;
            var changes = changeTracker.GetChanges();
            var changedOrder = changes[0];
            var updatedOrder = changes[0].Clone<Order>();
            updatedOrder.AcceptChanges();

            // Act
            changeTracker.MergeChanges(updatedOrder);

            // Assert
            Assert.Equal(date, order.OrderDate); // Changed order date is preserved
            Assert.Null(changedOrder.Customer); // GetChanges sets unchanges ref props to null
            Assert.NotNull(order.Customer); // Unchanged order.Customer is not overwritten
            Assert.Equal(TrackingState.Modified, origState); // Changed state is modified
            Assert.Equal(TrackingState.Unchanged, order.TrackingState); // State set to unchanged
        }

        [Fact]
        public void MergeChanges_Should_Set_Order_With_Modified_Customer_With_Db_Generated_Values()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var customer = order.Customer;
            var name = customer.CustomerName = "xxx";
            var changes = changeTracker.GetChanges();
            var updatedOrder = changes[0].Clone<Order>();
            var data = updatedOrder.Customer.Data = "yyy"; // simulate db-generated values
            updatedOrder.AcceptChanges();

            // Act
            changeTracker.MergeChanges(updatedOrder);

            // Assert
            Assert.Equal(name, order.Customer.CustomerName);
            Assert.Equal(data, order.Customer.Data);
        }

        #endregion

        #region MergeChanges: One-to-One

        [Fact]
        public void MergeChanges_Should_Set_Modified_Customer_With_Unchanged_Setting()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var customer = order.Customer;
            customer.CustomerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Customer = customer,
                Setting = "Setting1"
            };
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var name = customer.CustomerName = "xxx";
            var origState = customer.TrackingState;
            var changes = changeTracker.GetChanges();
            var changedCustomer = changes[0].Customer;
            var updatedOrder = changes[0].Clone<Order>();
            updatedOrder.AcceptChanges();

            // Act
            changeTracker.MergeChanges(updatedOrder);

            // Assert
            Assert.Equal(name, customer.CustomerName); // Changed customer name is preserved
            Assert.Null(changedCustomer.CustomerSetting); // GetChanges sets unchanges ref props to null
            Assert.NotNull(order.Customer.CustomerSetting); // Unchanged ref props not overwritten
            Assert.Equal(TrackingState.Modified, origState); // Changed state is modified
            Assert.Equal(TrackingState.Unchanged, customer.TrackingState); // State set to unchanged
        }

        [Fact]
        public void MergeChanges_Should_Set_Unchanged_Customer_With_Modified_Setting()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var customer = order.Customer;
            customer.CustomerSetting = new CustomerSetting
            {
                CustomerId = customer.CustomerId,
                Customer = customer,
                Setting = "Setting1"
            };
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var setting = customer.CustomerSetting.Setting = "xxx";
            var origState = customer.CustomerSetting.TrackingState;
            var changes = changeTracker.GetChanges();
            var changedCustomer = changes[0].Customer;
            var updatedOrder = changes[0].Clone<Order>();
            updatedOrder.AcceptChanges();

            // Act
            changeTracker.MergeChanges(updatedOrder);

            // Assert
            Assert.Equal(setting, customer.CustomerSetting.Setting); // Changed customer setting is preserved
            Assert.Equal(TrackingState.Modified, origState); // Changed state is modified
            Assert.Equal(TrackingState.Unchanged, customer.TrackingState); // State set to unchanged
        }
        
        #endregion

        #region MergeChanges: Many-to-Many

        [Fact]
        public void MergeChanges_Should_Set_Modified_Employee_With_Unchanged_Territories()
        {
            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var unchangedterritory = employee.Territories[0];
            var modifiedterritory = employee.Territories[1];
            var deletedterritory = employee.Territories[2];
            var addedExistingTerritory = database.Territories[3];
            var addedNewTerritory = new Territory
            {
                TerritoryId = "91360",
                TerritoryDescription = "SouthernCalifornia",
                Employees = new ChangeTrackingCollection<Employee> {employee}
            };
            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            var name = employee.LastName = "xxx";
            var origState = employee.TrackingState;
            var changes = changeTracker.GetChanges();
            var changedTerritories = changes[0].Territories;
            var updatedEmployee = changes[0].Clone<Employee>();
            updatedEmployee.AcceptChanges();

            // Act
            changeTracker.MergeChanges(updatedEmployee);

            // Assert
            Assert.Equal(name, employee.LastName); // Changed prop is preserved
            Assert.Empty(changedTerritories); // GetChanges sets unchanges ref props to null
            Assert.Equal(3, employee.Territories.Count); // Unchanged items preserved
        }

        [Fact]
        public void MergeChanges_Should_Merge_Updates_For_Unchanged_Employee_With_Changed_Territories()
        {
            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var unchangedTerritory = employee.Territories[0];
            var modifiedTerritory = employee.Territories[1];
            var deletedTerritory = employee.Territories[2];
            var addedExistingTerritory = database.Territories[3];
            var area1 = new Area { AreaId = 1, AreaName = "Northern", Territories = new ChangeTrackingCollection<Territory> { unchangedTerritory } };
            var area2 = new Area { AreaId = 2, AreaName = "Southern", Territories = new ChangeTrackingCollection<Territory> { modifiedTerritory } };
            var area3 = new Area { AreaId = 3, AreaName = "Eastern", Territories = new ChangeTrackingCollection<Territory> { deletedTerritory } };
            var area4 = new Area { AreaId = 4, AreaName = "Western", Territories = new ChangeTrackingCollection<Territory> { addedExistingTerritory } };
            var addedNewTerritory = new Territory
            {
                TerritoryId = "91360",
                TerritoryDescription = "SouthernCalifornia",
                Employees = new ChangeTrackingCollection<Employee> { employee },
                AreaId = 5,
                TrackingState = TrackingState.Added // Must explicitly mark as added
            };
            unchangedTerritory.Area = area1;
            unchangedTerritory.AreaId = area1.AreaId;
            modifiedTerritory.Area = area2;
            modifiedTerritory.AreaId = area2.AreaId;
            deletedTerritory.Area = area3;
            deletedTerritory.AreaId = area3.AreaId;
            addedExistingTerritory.Area = area4;
            addedExistingTerritory.AreaId = area4.AreaId;

            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            modifiedTerritory.TerritoryDescription = "xxx"; // mod prop
            modifiedTerritory.AreaId = 6; // mod FK prop
            employee.Territories.Remove(deletedTerritory); // should mark area deleted
            employee.Territories.Add(addedExistingTerritory); // should keep area unchanged
            employee.Territories.Add(addedNewTerritory); // should keep territory added
            addedExistingTerritory.Area.AreaName = "zzz"; // should mark area modified

            var changes = changeTracker.GetChanges(); // should exclude unchanged territory
            var updatedEmployee = UpdateEmployeesWithTerritories(changes)[0]; // rel entities, db-gen vals

            // Act
            changeTracker.MergeChanges(updatedEmployee);

            // Assert
            Assert.Contains(unchangedTerritory, employee.Territories); // Unchanged present
            Assert.Equal("zzz", addedExistingTerritory.Area.AreaName); // Area name updated
            Assert.Equal("yyy", addedNewTerritory.Data); // Db-generated value set
            Assert.Equal(addedNewTerritory.AreaId, addedNewTerritory.Area.AreaId); // Added territory Area set
            Assert.Equal(modifiedTerritory.AreaId, modifiedTerritory.Area.AreaId); // Modified territory Area set
            Assert.Same(addedExistingTerritory, employee.Territories.Single(t => t.TerritoryId == "02116")); // Ref equality
            Assert.Same(addedNewTerritory, employee.Territories.Single(t => t.TerritoryId == "91360")); // Ref equality
            Assert.Same(modifiedTerritory, employee.Territories.Single(t => t.TerritoryId == "01730")); // Ref equality
            Assert.DoesNotContain(deletedTerritory, employee.Territories); // Detail deleted
            ICollection cachedDeletes = ((ITrackingCollection)employee.Territories).CachedDeletes;
            Assert.Empty(cachedDeletes); // Cached deletes have been removed
        }

        #endregion

        #region MergeChanges Exceptions

        [Fact]
        public void MergeChanges_On_Equatable_Customer_Should_Not_Throw_ArgumentException()
        {
            // Arrange
            var customer = new Customer { CustomerId = "ALFKI" };
            var changeTracker = new ChangeTrackingCollection<Customer>(customer);

            // Act
            changeTracker.MergeChanges();

            // Assert
            Assert.True(true);
        }

        [Fact]
        public void MergeChanges_On_Equatable_PromotionalProduct_Should_Not_Throw_ArgumentException()
        {
            // Arrange
            var product = new MockNorthwind().Products.OfType<PromotionalProduct>().First();
            var changeTracker = new ChangeTrackingCollection<PromotionalProduct>(product);
            var clonedProduct = product.Clone();

            // Act
            changeTracker.MergeChanges(clonedProduct);

            // Assert
            Assert.True(true);
        }

        #endregion

        #endregion

        #region HasChanges Tests

        #region HasChanges: One-to-Many

        [Fact]
        public void HasChanges_Unchanged_Parent_Should_Return_False()
        {
            // Arrange
            var parent = new Parent("Parent");
            var changeTracker = new ChangeTrackingCollection<Parent>(parent);

            // Act
            bool hasChanges = parent.HasChanges();

            // Assert
            Assert.False(hasChanges);
        }

        [Fact]
        public void HasChanges_Modified_Parent_Should_Return_True()
        {
            // Arrange
            var parent = new Parent("Parent");
            var changeTracker = new ChangeTrackingCollection<Parent>(parent);
            parent.Name += "_Changed";

            // Act
            bool hasChanges = parent.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Added_Parent_Should_Return_True()
        {
            // Arrange
            var parent = new Parent("Parent");
            var changeTracker = new ChangeTrackingCollection<Parent>(true);
            changeTracker.Add(parent);

            // Act
            bool hasChanges = parent.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Deleted_Parent_Should_Return_True()
        {
            // Arrange
            var parent = new Parent("Parent");
            var changeTracker = new ChangeTrackingCollection<Parent>(parent);
            changeTracker.Remove(parent);

            // Act
            bool hasChanges = parent.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Parent_With_Unchanged_Children_Should_Return_False()
        {
            // Arrange
            var parent = new Parent("Parent")
            {
                Children = new ChangeTrackingCollection<Child>
                    {
                        new Child("Child1"), 
                        new Child("Child2")
                    }
            };
            var changeTracker = new ChangeTrackingCollection<Parent>(parent);

            // Act
            bool hasChanges = parent.HasChanges();

            // Assert
            Assert.False(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Parent_With_Modified_Child_Should_Return_True()
        {
            // Arrange
            var parent = new Parent("Parent")
            {
                Children = new ChangeTrackingCollection<Child>
                    {
                        new Child("Child1"), 
                        new Child("Child2")
                    }
            };
            var changeTracker = new ChangeTrackingCollection<Parent>(parent);
            parent.Children[0].Name += "_Changed";

            // Act
            bool hasChanges = parent.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Parent_With_Added_Child_Should_Return_True()
        {
            // Arrange
            var parent = new Parent("Parent")
            {
                Children = new ChangeTrackingCollection<Child>
                    {
                        new Child("Child1"), 
                        new Child("Child2")
                    }
            };
            var changeTracker = new ChangeTrackingCollection<Parent>(parent);
            parent.Children.Add(new Child("Child3"));

            // Act
            bool hasChanges = parent.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Parent_With_Removed_Child_Should_Return_True()
        {
            // Arrange
            var parent = new Parent("Parent")
            {
                Children = new ChangeTrackingCollection<Child>
                    {
                        new Child("Child1"), 
                        new Child("Child2")
                    }
            };
            var changeTracker = new ChangeTrackingCollection<Parent>(parent);
            parent.Children.RemoveAt(0);

            // Act
            bool hasChanges = parent.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Parent_With_Unchanged_Grandchildren_Should_Return_False()
        {
            // Arrange
            var parent = new Parent("Parent")
            {
                Children = new ChangeTrackingCollection<Child>
                    {
                        new Child("Child1")
                            { 
                                Children = new ChangeTrackingCollection<Child>
                                { 
                                    new Child("Grandchild1"),
                                    new Child("Grandchild2")
                                } 
                            }, 
                        new Child("Child2")
                    }
            };
            var changeTracker = new ChangeTrackingCollection<Parent>(parent);

            // Act
            bool hasChanges = parent.HasChanges();

            // Assert
            Assert.False(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Parent_With_Modified_Grandchild_Should_Return_True()
        {
            // Arrange
            var parent = new Parent("Parent")
            {
                Children = new ChangeTrackingCollection<Child>
                    {
                        new Child("Child1")
                            { 
                                Children = new ChangeTrackingCollection<Child>
                                { 
                                    new Child("Grandchild1"),
                                    new Child("Grandchild2")
                                } 
                            }, 
                        new Child("Child2")
                    }
            };
            var changeTracker = new ChangeTrackingCollection<Parent>(parent);
            parent.Children[0].Children[0].Name += "_Changed";

            // Act
            bool hasChanges = parent.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Parent_With_Added_Grandchild_Should_Return_True()
        {
            // Arrange
            var parent = new Parent("Parent")
            {
                Children = new ChangeTrackingCollection<Child>
                    {
                        new Child("Child1")
                            { 
                                Children = new ChangeTrackingCollection<Child>
                                { 
                                    new Child("Grandchild1"),
                                    new Child("Grandchild2")
                                } 
                            }, 
                        new Child("Child2")
                    }
            };
            var changeTracker = new ChangeTrackingCollection<Parent>(parent);
            parent.Children[0].Children.Add(new Child("Grandchild3"));

            // Act
            bool hasChanges = parent.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Parent_With_Removed_Grandchild_Should_Return_True()
        {
            // Arrange
            var parent = new Parent("Parent")
            {
                Children = new ChangeTrackingCollection<Child>
                    {
                        new Child("Child1")
                            { 
                                Children = new ChangeTrackingCollection<Child>
                                { 
                                    new Child("Grandchild1"),
                                    new Child("Grandchild2")
                                } 
                            }, 
                        new Child("Child2")
                    }
            };
            var changeTracker = new ChangeTrackingCollection<Parent>(parent);
            parent.Children[0].Children.RemoveAt(0);

            // Act
            bool hasChanges = parent.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Order_OrderDetail_With_Modified_Product_Should_Return_True()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.OrderDetails[0].Product.ProductName = "xxx";

            // Act
            bool hasChanges = order.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Order_OrderDetail_With_Product_Set_To_Null_Should_Return_False()
        {
            // NOTE: Setting OrderDetail.Product to null is not considered a change,
            // because it will not result in any updated entities.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.OrderDetails[0].Product = null;

            // Act
            bool hasChanges = order.HasChanges();

            // Assert
            Assert.False(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Order_OrderDetail_With_Product_Set_To_Unchanged_Product_Should_Return_False()
        {
            // NOTE: Setting null OrderDetail.Product to a product is not considered a change,
            // because it will not result in any updated entities.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var product = database.Products[0];
            order.OrderDetails[0].Product = product;

            // Act
            bool hasChanges = order.HasChanges();

            // Assert
            Assert.False(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Order_OrderDetail_Set_Product_To_Added_Product_Should_Return_True()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var product = database.Products[0];
            product.TrackingState = TrackingState.Added;
            order.OrderDetails[0].Product = product;

            // Act
            bool hasChanges = order.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Order_OrderDetail_Set_Product_To_Deleted_Product_Should_Return_True()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            var product = database.Products[0];
            product.TrackingState = TrackingState.Deleted;
            order.OrderDetails[0].Product = product;

            // Act
            bool hasChanges = order.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        #endregion

        #region HasChanges: Many-to-One

        [Fact]
        public void HasChanges_Unchanged_Order_Customer_With_Unchanged_Territory_Should_Return_False()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var territory = database.Territories[0];
            var employee = database.Employees[0];
            territory.Employees = new ChangeTrackingCollection<Employee> { employee };
            order.Customer.Territory = territory;
            var changeTracker = new ChangeTrackingCollection<Order>(order);

            // Act
            bool hasChanges = order.HasChanges();

            // Assert
            Assert.False(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Order_Customer_With_Territory_Set_To_Null_Should_Return_False()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var territory = database.Territories[0];
            var employee = database.Employees[0];
            territory.Employees = new ChangeTrackingCollection<Employee> { employee };
            order.Customer.Territory = territory;
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.Customer.Territory = null;

            // Act
            bool hasChanges = order.HasChanges();

            // Assert
            Assert.False(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Order_Customer_With_Territory_Set_To_Unchanged_Territory_Should_Return_False()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var territory = database.Territories[0];
            var employee = database.Employees[0];
            territory.Employees = new ChangeTrackingCollection<Employee> { employee };
            order.Customer.Territory = territory;
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.Customer.Territory = database.Territories[1];

            // Act
            bool hasChanges = order.HasChanges();

            // Assert
            Assert.False(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Order_Customer_With_Modified_Territory_Should_Return_True()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var territory = database.Territories[0];
            var employee = database.Employees[0];
            territory.Employees = new ChangeTrackingCollection<Employee> { employee };
            order.Customer.Territory = territory;
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            territory.Data = "xxx";

            // Act
            bool hasChanges = order.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Order_Customer_Territory_With_Modified_Employee_Should_Return_True()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var territory = database.Territories[0];
            var employee = database.Employees[0];
            territory.Employees = new ChangeTrackingCollection<Employee> { employee };
            order.Customer.Territory = territory;
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            territory.Employees[0].LastName = "xxx";

            // Act
            bool hasChanges = order.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Order_Customer_Territory_With_Added_Employee_Should_Return_True()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var territory = database.Territories[0];
            var employee = database.Employees[0];
            territory.Employees = new ChangeTrackingCollection<Employee> { employee };
            order.Customer.Territory = territory;
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            territory.Employees.Add(database.Employees[1]);

            // Act
            bool hasChanges = order.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Order_Customer_Territory_With_Removed_Employee_Should_Return_True()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var territory = database.Territories[0];
            var employee = database.Employees[0];
            territory.Employees = new ChangeTrackingCollection<Employee> { employee };
            order.Customer.Territory = territory;
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            territory.Employees.Remove(employee);

            // Act
            bool hasChanges = order.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        #endregion

        #region HasChanges: One-to-One

        [Fact]
        public void HasChanges_Unchanged_Order_Customer_With_Unchanged_Setting_Should_Return_False()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            order.Customer.CustomerSetting = new CustomerSetting
            {
                CustomerId = order.CustomerId,
                Customer = order.Customer,
                Setting = "Setting1"
            };
            var changeTracker = new ChangeTrackingCollection<Order>(order);

            // Act
            bool hasChanges = order.HasChanges();

            // Assert
            Assert.False(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Order_Customer_With_Modified_Setting_Should_Return_True()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            order.Customer.CustomerSetting = new CustomerSetting
            {
                CustomerId = order.CustomerId,
                Customer = order.Customer,
                Setting = "Setting1"
            };
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.Customer.CustomerSetting.Setting = "xxx";

            // Act
            bool hasChanges = order.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Order_Customer_With_Setting_Set_To_Null_Should_Return_False()
        {
            // NOTE: Setting ref prop to false will not result in updated entities.

            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            order.Customer.CustomerSetting = new CustomerSetting
            {
                CustomerId = order.CustomerId,
                Customer = order.Customer,
                Setting = "Setting1"
            };
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.Customer.CustomerSetting = null;

            // Act
            bool hasChanges = order.HasChanges();

            // Assert
            Assert.False(hasChanges);
        }

        #endregion

        #region HasChanges: Many-to-Many

        [Fact]
        public void HasChanges_Unchanged_Employee_With_Unchanged_Territories_Should_Return_False()
        {
            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var changeTracker = new ChangeTrackingCollection<Employee>(employee);

            // Act
            bool hasChanges = employee.HasChanges();

            // Assert
            Assert.False(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Employee_With_Modified_Territory_Should_Return_True()
        {
            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            employee.Territories[0].Data = "xxx";

            // Act
            bool hasChanges = employee.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Employee_With_Added_Territory_Should_Return_True()
        {
            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            employee.Territories.Add(database.Territories[4]);

            // Act
            bool hasChanges = employee.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        [Fact]
        public void HasChanges_Unchanged_Employee_With_Removed_Territory_Should_Return_True()
        {
            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            employee.Territories.RemoveAt(0);

            // Act
            bool hasChanges = employee.HasChanges();

            // Assert
            Assert.True(hasChanges);
        }

        #endregion

        #endregion

        #region Clone Tests

        [Fact]
        public void Clone_Of_ChangeTrackingCollection_Should_Create_Deep_Copy()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var order3 = database.Orders[3];
            var customer = order.Customer;
            var details = order.OrderDetails;
            var changeTracker = new ChangeTrackingCollection<Order>(order, order3);

            // Act
            var clonedChangeTracker = changeTracker.Clone();

            // Assert
            Assert.NotSame(order, clonedChangeTracker[0]);
            Assert.NotSame(customer, clonedChangeTracker[0].Customer);
            Assert.NotSame(details, clonedChangeTracker[0].OrderDetails);
            Assert.True(order.IsEquatable(clonedChangeTracker[0]));
            Assert.True(customer.IsEquatable(clonedChangeTracker[0].Customer));
            Assert.True(object.ReferenceEquals(order.Customer, order3.Customer));
            Assert.False(object.ReferenceEquals(order.Customer, clonedChangeTracker[0].Customer));
            Assert.True(object.ReferenceEquals(clonedChangeTracker[0].Customer, clonedChangeTracker[1].Customer));
        }

        #endregion

        #region Helpers

        private List<Order> AddOrders(MockNorthwind database, params Order[] origOrders)
        {
            var addedOrders = new List<Order>();
            for (int i = 0; i < origOrders.Length; i++)
            {
                // Simulate serialization
                var origOrder = origOrders[i];
                var addedOrder = origOrder.Clone<Order>();

                // Simulate load related entities
                string customerId = i == 0 ? "ALFKI" : "ANATR";
                addedOrder.Customer = database.Customers.Single(c => c.CustomerId == customerId);

                // Simulate db-generated values
                addedOrder.OrderId = new Random().Next(1000);
                addedOrder.OrderDate = origOrder.OrderDate.AddDays(1);
                addedOrder.AcceptChanges();
                addedOrders.Add(addedOrder);
            }
            return addedOrders;
        }

        private List<Order> UpdateOrders(MockNorthwind database, params Order[] origOrders)
        {
            var updatedOrders = new List<Order>();
            for (int i = 0; i < origOrders.Length; i++)
            {
                // Simulate serialization
                var origOrder = origOrders[i];
                var updatedOrder = origOrder.Clone<Order>();

                // Simulate load related entities
                string customerId = i == 0 ? "ALFKI" : "ANATR";
                updatedOrder.Customer = database.Customers.Single(c => c.CustomerId == customerId);

                // Simulate db-generated values
                updatedOrder.OrderDate = origOrder.OrderDate.AddDays(1);
                updatedOrder.AcceptChanges();
                updatedOrders.Add(updatedOrder);
            }
            return updatedOrders;
        }

        private List<Order> UpdateOrdersWithDetails(MockNorthwind database, IEnumerable<Order> changes)
        {
            var updatedOrders = new List<Order>();
            foreach (var origOrder in changes)
            {
                // Simulate serialization
                var updatedOrder = origOrder.Clone<Order>();

                // Simulate load related entities
                updatedOrder.OrderDetails[1].Product = database.Products.Single(p => p.ProductId == 1);
                updatedOrder.OrderDetails[2].Product = database.Products.Single(p => p.ProductId == 51);

                // Simulate db-generated values
                updatedOrder.OrderDetails[1].UnitPrice++;
                updatedOrder.AcceptChanges();
                updatedOrders.Add(updatedOrder);
            }
            return updatedOrders;
        }

        private List<Employee> UpdateEmployeesWithTerritories(IEnumerable<Employee> changes)
        {
            var updatedEmployees = new List<Employee>();
            foreach (var origEmployee in changes)
            {
                // Simulate serialization
                var updatedEmployee = origEmployee.Clone<Employee>();

                // Simulate load related entities
                var addedNewTerritory = updatedEmployee.Territories.Single(t => t.TerritoryId == "91360");
                var modifiedTerritory = updatedEmployee.Territories.Single(t => t.TerritoryId == "01730");
                var area5 = new Area { AreaId = 5, AreaName = "Southwestern", 
                    Territories = new ChangeTrackingCollection<Territory> { addedNewTerritory }};
                var area6 = new Area { AreaId = 6, AreaName = "Central", 
                    Territories = new ChangeTrackingCollection<Territory> { modifiedTerritory }};
                addedNewTerritory.Area = area5;
                modifiedTerritory.Area = area6;

                // Simulate db-generated values
                addedNewTerritory.Data = "yyy";

                updatedEmployee.AcceptChanges();
                updatedEmployees.Add(updatedEmployee);
            }
            return updatedEmployees;
        }

        #endregion
    }
}


<|start_filename|>Extensions/VS2012/Deploy/TrackableEntities.WcfItemWizard/WcfServiceTypeWizard.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.TemplateWizard;
using TrackableItemTemplateWizard;

namespace TrackableEntities.WcfItemWizard
{
    public class WcfServiceTypeWizard : IWizard
    {
        public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, 
            WizardRunKind runKind, object[] customParams)
        {
            // Get referenced types
            var dte2 = (DTE2)automationObject;
            List<Type> modelTypes = GetReferencedTypes(dte2).ToList();

            // Prompt user for Entity and DbContext names
            var dialog = new ModelTypesDialog(modelTypes, 
                "Trackable WCF Service Type",
                "Add WCF service contract and type with CRUD operations using Trackable Entities.");
            if (dialog.ShowDialog() == DialogResult.Cancel)
                throw new WizardBackoutException();

            string entityNamespace = dialog.ModelTypesInfo.EntityNamespace;
            string entityName = dialog.ModelTypesInfo.EntityName;
            string entitySetName = dialog.ModelTypesInfo.EntitySetName;
            string dbContextName = dialog.ModelTypesInfo.DbContextName;

            replacementsDictionary.Add("$entityNamespace$", entityNamespace);
            replacementsDictionary.Add("$entityName$", entityName);
            replacementsDictionary.Add("$entitySetName$", entitySetName);
            replacementsDictionary.Add("$dbContextName$", dbContextName);
        }

        public void BeforeOpeningFile(ProjectItem projectItem)
        {
        }

        public void ProjectFinishedGenerating(Project project)
        {
        }

        public void ProjectItemFinishedGenerating(ProjectItem projectItem)
        {
        }

        public void RunFinished()
        {
        }

        public bool ShouldAddProjectItem(string filePath)
        {
            return true;
        }

        private IEnumerable<Type> GetReferencedTypes(DTE2 dte2)
        {
            Project activeProject = dte2.ActiveSolutionProjects[0];
            var project = activeProject.Object as VSLangProj.VSProject;
            if (project != null)
            {
                foreach (VSLangProj.Reference reference in project.References)
                {
                    if (reference.SourceProject != null)
                    {
                        Assembly assembly = Assembly.LoadFrom(reference.Path);
                        foreach (Type type in assembly.GetTypes())
                        {
                            yield return type;
                        }
                    }
                }
            }
        }
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/ClientEntities/Order.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using TrackableEntities.Client;

namespace TrackableEntities.Tests.Acceptance.ClientEntities
{
    [JsonObject(IsReference = true)]
    public class Order : EntityBase
    {
        private int _orderId;
        public int OrderId
        {
            get { return _orderId; }
            set
            {
                if (value == _orderId) return;
                _orderId = value;
                NotifyPropertyChanged();
            }
        }

        private DateTime _orderDate;
        public DateTime OrderDate
        {
            get { return _orderDate; }
            set
            {
                if (value == _orderDate) return;
                _orderDate = value;
                NotifyPropertyChanged();
            }
        }
        private string _customerId;
        public string CustomerId
        {
            get { return _customerId; }
            set
            {
                if (value == _customerId) return;
                _customerId = value;
                NotifyPropertyChanged();
            }
        }

        private Customer _customer;
        public Customer Customer
        {
            get { return _customer; }
            set
            {
                if (value == _customer) return;
                _customer = value;
                CustomerChangeTracker = _customer == null ? null 
                    : new ChangeTrackingCollection<Customer> { _customer };
                NotifyPropertyChanged();
            }
        }
        private ChangeTrackingCollection<Customer> CustomerChangeTracker { get; set; }

        private ChangeTrackingCollection<OrderDetail> _orderDetails;
        public ChangeTrackingCollection<OrderDetail> OrderDetails
        {
            get { return _orderDetails; }
            set
            {
                if (Equals(value, _orderDetails)) return;
                _orderDetails = value;
                NotifyPropertyChanged();
            }
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Relations/WebApiSample.WebApi/Controllers/EmployeeController.cs<|end_filename|>
﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using TrackableEntities;
using TrackableEntities.EF6;
using TrackableEntities.Common;
using WebApiSample.Service.Entities.Models;
using WebApiSample.Service.Entities.Contexts;

namespace WebApiSample.Service.WebApi.Controllers
{
    public class EmployeeController : ApiController
    {
        private readonly NorthwindSlimContext _dbContext = new NorthwindSlimContext();

        // GET api/Employee
        [ResponseType(typeof(IEnumerable<Employee>))]
        public async Task<IHttpActionResult> GetEmployees()
        {
	        IEnumerable<Employee> employees = await _dbContext.Employees.ToListAsync();
	
            return Ok(employees);
        }

        // GET api/Employee/5
        [ResponseType(typeof(Employee))]
        public async Task<IHttpActionResult> GetEmployee(int id)
        {
	        Employee employee = await _dbContext.Employees
                .Include(e => e.Territories)
                .SingleOrDefaultAsync(e => e.EmployeeId == id);
	
            if (employee == null)
            {
                return NotFound();
            }

            return Ok(employee);
        }

        // POST api/Employee
        [ResponseType(typeof(Employee))]
        public async Task<IHttpActionResult> PostEmployee(Employee employee)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            employee.TrackingState = TrackingState.Added;
            _dbContext.ApplyChanges(employee);

            await _dbContext.SaveChangesAsync();

            await _dbContext.LoadRelatedEntitiesAsync(employee);
            employee.AcceptChanges();
            return CreatedAtRoute("DefaultApi", new { id = employee.EmployeeId }, employee);
        }

        // PUT api/Employee
        [ResponseType(typeof(Employee))]
        public async Task<IHttpActionResult> PutEmployee(Employee employee)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            _dbContext.ApplyChanges(employee);

            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!_dbContext.Employees.Any(e => e.EmployeeId == employee.EmployeeId))
                {
                    return Conflict();
                }
                throw;
            }

			await _dbContext.LoadRelatedEntitiesAsync(employee);
			employee.AcceptChanges();
	        return Ok(employee);
        }

        // DELETE api/Employee/5
        public async Task<IHttpActionResult> DeleteEmployee(int id)
        {
			Employee employee = await _dbContext.Employees
			    .Include(e => e.Territories) // Include child entities
				.SingleOrDefaultAsync(e => e.EmployeeId == id);
			if (employee == null)
            {
                return Ok();
            }

			employee.TrackingState = TrackingState.Deleted;
			_dbContext.ApplyChanges(employee);

            try
            {
	            await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!_dbContext.Employees.Any(e => e.EmployeeId == employee.EmployeeId))
                {
                    return Conflict();
                }
                throw;
            }

            return Ok();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _dbContext.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}

<|start_filename|>Samples/VS2013/WcfSample/WcfSample.Client.Entities/Models/CustomerSetting.cs<|end_filename|>
using TrackableEntities.Client;

namespace WcfSample.Client.Entities.Models
{
    public partial class CustomerSetting : EntityBase
    {
		public string CustomerId
		{ 
			get { return _CustomerId; }
			set
			{
				if (Equals(value, _CustomerId)) return;
				_CustomerId = value;
				NotifyPropertyChanged(() => CustomerId);
			}
		}
		private string _CustomerId;

		public string Setting
		{ 
			get { return _Setting; }
			set
			{
				if (Equals(value, _Setting)) return;
				_Setting = value;
				NotifyPropertyChanged(() => Setting);
			}
		}
		private string _Setting;

		public Customer Customer
		{
			get { return _Customer; }
			set
			{
				if (Equals(value, _Customer)) return;
				_Customer = value;
				CustomerChangeTracker = _Customer == null ? null
					: new ChangeTrackingCollection<Customer> { _Customer };
				NotifyPropertyChanged(() => Customer);
			}
		}
		private Customer _Customer;
		private ChangeTrackingCollection<Customer> CustomerChangeTracker { get; set; }

	}
}


<|start_filename|>Source/Tests/TrackableEntities.Client.Tests.Extensions/TrackableExtensionsTests.cs<|end_filename|>
﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using TrackableEntities.Client.Tests.Entities.Mocks;
using TrackableEntities.Client.Tests.Entities.FamilyModels;
using TrackableEntities.Client.Tests.Entities.NorthwindModels;
using TrackableEntities.Common;
using Xunit;

namespace TrackableEntities.Client.Tests.Extensions
{
    public class TrackableExtensionsTests
    {
        #region Setup

        // Mock database
        MockFamily _family;

        public TrackableExtensionsTests()
        {
            // Create new mock database for each test
            _family = new MockFamily();
        }

        #endregion

        #region Set Tracking Tests

        [Fact]
        public void Parent_Set_Tracking_Should_Enable_Tracking_For_Children()
        {
            // Arrange
            var parent = _family.Parent;

            // Act
            parent.SetTracking(true);

            // Assert
            IEnumerable<bool> trackings = GetTrackings(parent);
            Assert.True(trackings.All(t => t));
        }

        [Fact]
        public void Parent_Set_Tracking_Should_Disable_Tracking_For_Children()
        {
            // Arrange
            var parent = _family.Parent;
            parent.SetTracking(true);

            // Act
            parent.SetTracking(false);

            // Assert
            IEnumerable<bool> trackings = GetTrackings(parent);
            Assert.True(trackings.All(t => !t));
        }

        [Fact]
        public void Collection_Set_Tracking_Should_Enable_Tracking_For_Children()
        {
            // Arrange
            var parent = _family.Parent;
            var changeTracker = new ChangeTrackingCollection<Parent>();
            changeTracker.Add(parent);

            // Act
            changeTracker.Tracking = true;

            // Assert
            Assert.True(changeTracker.Tracking);
            IEnumerable<bool> trackings = GetTrackings(parent);
            Assert.True(trackings.All(t => t));
        }

        [Fact]
        public void Collection_Ctor_Should_Disable_Tracking_For_Children()
        {
            // Arrange
            var parent = _family.Parent;

            // Act
            var changeTracker = new ChangeTrackingCollection<Parent>(parent);

            // Assert
            Assert.True(changeTracker.Tracking);
            IEnumerable<bool> trackings = GetTrackings(parent);
            Assert.True(trackings.All(t => t));
        }

        #endregion

        #region Set State Tests

        [Fact]
        public void Parent_Set_State_As_Added_Should_Mark_Children_As_Added()
        {
            // Arrange
            var parent = _family.Parent;

            // Act
            parent.SetState(TrackingState.Added, null);

            // Assert
            IEnumerable<TrackingState> trackings = GetStates(parent);
            Assert.True(trackings.All(t => t == TrackingState.Added));
        }

        [Fact]
        public void Parent_Set_State_As_Deleted_Should_Mark_Children_As_Deleted()
        {
            // Arrange
            var parent = _family.Parent;

            // Act
            parent.SetState(TrackingState.Deleted, null);

            // Assert
            IEnumerable<TrackingState> trackings = GetStates(parent);
            Assert.True(trackings.All(t => t == TrackingState.Deleted));
        }

        [Fact]
        public void Parent_Set_State_As_Deleted_Should_Mark_Added_Children_As_Unchanged()
        {
            // NOTE: Deleting an added child should not mark it as deleted, but mark
            // it as unchanged because it says it was not really added in the first place.

            // Arrange
            var parent = _family.Parent;
            parent.TrackingState = TrackingState.Added;
            parent.Children.ToList().ForEach(c1 =>
            {
                c1.TrackingState = TrackingState.Added;
                c1.Children.ToList().ForEach(c2 =>
                {
                    c2.TrackingState = TrackingState.Added;
                    c2.Children.ToList().ForEach(c3 =>
                    {
                        c3.TrackingState = TrackingState.Added;
                    });
                });
            });

            // Act
            parent.SetState(TrackingState.Deleted, null);

            // Assert
            IEnumerable<TrackingState> trackings = GetStates(parent);
            Assert.True(trackings.All(t => t == TrackingState.Unchanged));
        }

        [Fact]
        public void Collection_Set_State_As_Deleted_Should_Mark_Children_As_Deleted()
        {
            // Arrange
            var parent = _family.Parent;
            var changeTracker = new ChangeTrackingCollection<Parent>(parent);

            // Act
            changeTracker.Remove(parent);

            // Assert
            Assert.Equal(TrackingState.Deleted, parent.TrackingState);
            IEnumerable<TrackingState> trackings = GetStates(parent);
            Assert.True(trackings.All(t => t == TrackingState.Deleted));
        }

        [Fact]
        public void Collection_Added_Set_State_As_Deleted_Should_Mark_Children_As_Unchanged()
        {
            // Arrange
            var parent = _family.Parent;
            var changeTracker = new ChangeTrackingCollection<Parent>(true);
            changeTracker.Add(parent);

            // Act
            changeTracker.Remove(parent);

            // Assert
            Assert.Equal(TrackingState.Unchanged, parent.TrackingState);
            IEnumerable<TrackingState> trackings = GetStates(parent);
            Assert.True(trackings.All(t => t == TrackingState.Unchanged));
        }

        [Fact]
        public void Parent_Set_Modified_Props_Should_Set_Children()
        {
            // Arrange
            var parent = _family.Parent;

            // Act
            parent.SetModifiedProperties(new List<string> { "Children" });

            // Assert
            IEnumerable<ICollection<string>> modifieds = GetModifieds(parent);
            Assert.True(modifieds.All(t => t.Contains("Children")));
        }

        [Fact]
        public void Child_Set_Modified_Props_Should_Not_Set_Parent_Siblings()
        {
            // NOTE: SetModifiedProperties should only set ModifiedProperties on
            // downstream 1-M entities.

            // Arrange
            const string propName = "UnitPrice";
            var nw = new MockNorthwind();
            var order = nw.Orders[0];
            var customer = order.Customer;
            var detail1 = order.OrderDetails[0];
            var detail2 = order.OrderDetails[1];
            var detail3 = order.OrderDetails[2];
            detail1.Order = order;
            detail2.Order = order;
            detail3.Order = order;

            var visitationHelper = new ObjectVisitationHelper(null);
            visitationHelper.TryVisit(order.OrderDetails);

            // Act
            detail1.SetModifiedProperties(new List<string> { propName }, visitationHelper.Clone());

            // Assert
            Assert.Null(order.ModifiedProperties);
            Assert.Null(customer.ModifiedProperties);
            Assert.Null(detail1.ModifiedProperties);
            Assert.Null(detail2.ModifiedProperties);
            Assert.Null(detail3.ModifiedProperties);
        }

        #endregion

        #region GetChanges Tests

        [Fact]
        public void Collection_GetChanges_Should_Add_Only_Modified_Children()
        {
            // Arrange
            var parent = new Parent("Parent")
            {
                Children = new ChangeTrackingCollection<Child>
                    {
                        new Child("Child1"), 
                        new Child("Child2")
                    }
            };
            var changeTracker = new ChangeTrackingCollection<Parent>(parent);
            parent.Children[0].Name += "_Changed";

            // Act
            var changes = changeTracker.GetChanges();
            var changedParent = changes.First();

            // Assert
            Assert.Equal(1, changes.Count);
            Assert.Equal(1, changedParent.Children.Count);
        }

        [Fact]
        public void Collection_GetChanges_Should_Add_Only_Deleted_Children()
        {
            // Arrange
            var parent = new Parent("Parent")
            {
                Children = new ChangeTrackingCollection<Child>
                    {
                        new Child("Child1")
                    }
            };
            var changeTracker = new ChangeTrackingCollection<Parent>(parent);
            parent.Children.RemoveAt(0);

            // Act
            var changes = changeTracker.GetChanges();
            var changedParent = changes.First();

            // Assert
            Assert.Equal(1, changes.Count);
            Assert.Equal(1, changedParent.Children.Count);
        }

        [Fact]
        public void Collection_GetChanges_Should_Add_Only_Added_Modified_Deleted_Children()
        {
            // Arrange
            var parent = new Parent("Parent")
            {
                Children = new ChangeTrackingCollection<Child>
                    {
                        new Child("Child1"), 
                        new Child("Child2"),
                        new Child("Child3")
                    }
            };
            var changeTracker = new ChangeTrackingCollection<Parent>(parent);
            parent.Children.Add(new Child("Child4"));
            parent.Children[0].Name += "_Changed";
            parent.Children.RemoveAt(2);

            // Act
            var changes = changeTracker.GetChanges();
            var changedParent = changes.First();

            // Assert
            Assert.Equal(1, changes.Count);
            Assert.Equal(3, changedParent.Children.Count);
        }

        #endregion

        #region Clone Tests

        [Fact]
        public void Clone_Should_Deep_Copy_Object()
        {
            // Arrange
            var parentOrig = _family.Parent;

            // Act
            var parentCopy = parentOrig.Clone<Parent>();

            // Assert
            Assert.NotSame(parentOrig, parentCopy);
            Assert.NotSame(parentOrig.Children[0], parentCopy.Children[0]);
            Assert.NotSame(parentOrig.Children[1], parentCopy.Children[1]);
            Assert.NotSame(parentOrig.Children[2], parentCopy.Children[2]);
            Assert.NotSame(parentOrig.Children[0].Children[0], parentCopy.Children[0].Children[0]);
            Assert.NotSame(parentOrig.Children[1].Children[0], parentCopy.Children[1].Children[0]);
            Assert.NotSame(parentOrig.Children[2].Children[0], parentCopy.Children[2].Children[0]);
        }

        [Fact]
        public void Collection_Clone_Should_Deep_Copy_Category()
        {
            // Arrange
            var database = new MockNorthwind();
            var categoryOrig = database.Categories[0];

            // Act
            var categoryCopy = categoryOrig.Clone<Category>();

            // Assert
            Assert.NotSame(categoryOrig, categoryCopy);
            Assert.NotSame(categoryOrig.Products[0], categoryCopy.Products[0]);
            Assert.NotSame(categoryOrig.Products[1], categoryCopy.Products[1]);
            Assert.Equal(categoryOrig.Products.Count, categoryCopy.Products.Count);
            for (int i = 0; i < categoryOrig.Products.Count; ++i)
                Assert.Same(categoryOrig.Products[i].GetType(), categoryCopy.Products[i].GetType());
        }

        [Fact]
        public void Collection_Clone_Should_Deep_Copy_Product()
        {
            // Arrange
            var database = new MockNorthwind();
            var productOrig = database.Products[0];

            // Act
            var productCopy = productOrig.Clone<Product>();

            // Assert
            Assert.NotSame(productOrig, productCopy);
            Assert.NotSame(productOrig.Category, productCopy.Category);
        }

        #endregion

        #region Restore and Remove Deletes Tests

        [Fact]
        public void Collection_Restore_Deletes_Should_Add_Deleted_Items()
        {
            // Arrange
            var parent = new Parent("Parent")
            {
                Children = new ChangeTrackingCollection<Child>
                    {
                        new Child("Child1"), 
                        new Child("Child2"),
                        new Child("Child3")
                    }
            };
            parent.Children.Tracking = true;
            parent.Children.RemoveAt(2);

            // Act
            var trackableColl = (ITrackingCollection)parent.Children;
            trackableColl.RestoreDeletes();

            // Assert
            Assert.Equal(3, trackableColl.Count);
        }

        [Fact]
        public void Collection_Remove_Deletes_Should_Remove_Added_Deleted_Items()
        {
            // Arrange
            var parent = new Parent("Parent")
            {
                Children = new ChangeTrackingCollection<Child>
                    {
                        new Child("Child1"), 
                        new Child("Child2"),
                        new Child("Child3")
                    }
            };
            parent.Children[0].TrackingState = TrackingState.Deleted;
            parent.Children.Tracking = true;
            parent.Children.RemoveAt(0);
            parent.Children.RestoreDeletes();

            // Act
            var trackableColl = (ITrackingCollection)parent.Children;
            trackableColl.RemoveRestoredDeletes();

            // Assert
            Assert.Equal(2, trackableColl.Count);
        }

        [Fact]
        public void Item_Restore_Deletes_Should_Recursively_Add_Deleted_Items()
        {
            // Arrange
            var parent = new Parent("Parent")
            {
                Children = new ChangeTrackingCollection<Child>
                    {
                        new Child("Child1")
                        { 
                            Children = new ChangeTrackingCollection<Child>
                                {
                                    new Child("Grandchild1"),
                                    new Child("Grandchild2")
                                }
                        }
                    }
            };
            var count = parent.Children[0].Children.Count;
            parent.SetTracking(true);
            parent.Children[0].Children.RemoveAt(1);

            // Act
            parent.Children[0].Children.RestoreDeletes();

            // Assert
            Assert.Equal(count, parent.Children[0].Children.Count);
        }

        [Fact]
        public void Item_Remove_Deletes_Should_Recursively_Remove_Added_Deleted_Items()
        {
            // Arrange
            var parent = new Parent("Parent")
            {
                Children = new ChangeTrackingCollection<Child>
                    {
                        new Child("Child1")
                        { 
                            Children = new ChangeTrackingCollection<Child>
                                {
                                    new Child("Grandchild1"),
                                    new Child("Grandchild2")
                                }
                        }
                    }
            };
            var deleted = parent.Children[0].Children[1];
            parent.Children[0].Children.Tracking = true;
            parent.Children[0].Children.RemoveAt(1);
            parent.Children[0].Children.RestoreDeletes();

            // Act
            var trackableColl = (ITrackingCollection)parent.Children[0].Children;
            trackableColl.RemoveRestoredDeletes();

            // Assert
            Assert.Equal(1, parent.Children[0].Children.Count);
            Assert.DoesNotContain(deleted, (ITrackingCollection<Child>)trackableColl);
        }

        [Fact]
        public void Order_Remove_Deletes_Should_Remove_Deleted_OrderDetails()
        {
            // Arrange
            var database = new MockNorthwind();
            var order = database.Orders[0];
            var deleted1 = order.OrderDetails[0];
            var deleted2 = order.OrderDetails[2];
            var changeTracker = new ChangeTrackingCollection<Order>(order);
            order.OrderDetails.Remove(deleted1);
            order.OrderDetails.Remove(deleted2);
            changeTracker.RestoreDeletes();

            // Act
            changeTracker.RemoveRestoredDeletes();

            // Assert
            Assert.Equal(1, order.OrderDetails.Count);
            Assert.DoesNotContain(deleted1, changeTracker.Cast<object>());
            Assert.DoesNotContain(deleted2, changeTracker.Cast<object>());
        }

        #endregion

        #region IsEquatable Tests

        [Fact]
        public void IsEquatable_Should_Return_False_If_SetEntityIdentifier_Not_Called()
        {
            // Arrange
            var northwind = new MockNorthwind();
            var customer1 = northwind.Customers[0];
            var customer2 = northwind.Customers[1];

            // Act
            bool areEquatable = customer1.IsEquatable(customer2);

            // Assert
            Assert.False(areEquatable);
        }

        [Fact]
        public void IsEquatable_Should_Return_True_If_SetEntityIdentifier_Called()
        {
            // Arrange
            var northwind = new MockNorthwind();
            var customer1 = northwind.Customers[0];
            var customer2 = northwind.Customers[1];
            customer1.SetEntityIdentifier();
            customer2.SetEntityIdentifier(customer1);

            // Act
            bool areEquatable = customer1.IsEquatable(customer2);

            // Assert
            Assert.True(areEquatable);
        }

        [Fact]
        public void IsEquatable_Should_Return_False_If_EntityIdentifier_Cleared()
        {
            // Arrange
            var northwind = new MockNorthwind();
            var customer1 = northwind.Customers[0];
            var customer2 = northwind.Customers[1];
            customer1.SetEntityIdentifier();
            customer2.SetEntityIdentifier(customer1);

            customer1.SetEntityIdentifier(new Customer()); // Cleared

            // Act
            bool areEquatable = customer1.IsEquatable(customer2);

            // Assert
            Assert.False(areEquatable);
        }

        [Fact]
        public void IsEquatable_Should_Return_False_If_EntityIdentifier_Reset()
        {
            // Arrange
            var northwind = new MockNorthwind();
            var customer1 = northwind.Customers[0];
            var customer2 = northwind.Customers[1];
            customer1.SetEntityIdentifier();
            customer2.SetEntityIdentifier(customer1);
            bool wereEquatable = customer1.IsEquatable(customer2);

            // Act
            customer1.SetEntityIdentifier(new Customer()); // Cleared
            customer1.SetEntityIdentifier(); // Reset
            bool areEquatable = customer1.IsEquatable(customer2);

            // Assert
            Assert.True(wereEquatable);
            Assert.False(areEquatable);
        }

        #endregion

        #region NotifyPropertyChanged Tests

        [Fact]
        public void Product_Property_Setter_Should_Fire_PropertyChanged_Event()
        {
            // Arrange
            var northwind = new MockNorthwind();
            var product = northwind.Products[0];
            var subscriber = new Subscriber<Product>
            {
                Model = product
            };

            // Act
            product.ProductName += "_X";

            // Assert
            Assert.True(subscriber.ModelChanged);
            Assert.Equal("ProductName", subscriber.ChangedPropertyName);
        }

        [Fact]
        public void PromotionalProduct_Property_Setter_Should_Fire_PropertyChanged_Event()
        {
            // Arrange
            var northwind = new MockNorthwind();
            var product = northwind.Products.OfType<PromotionalProduct>().First();
            var subscriber = new Subscriber<Product>
            {
                Model = product
            };

            // Act
            product.PromoCode += "_X";

            // Assert
            Assert.True(subscriber.ModelChanged);
            Assert.Equal("PromoCode", subscriber.ChangedPropertyName);
        }

        #endregion

        #region Helper Methods

        private IEnumerable<bool> GetTrackings(Parent parent)
        {
            var trackings = new List<bool>();
            trackings.Add(parent.Children.Tracking);
            trackings.AddRange(from c in parent.Children
                               let ch = c.Children
                               select ch.Tracking);
            trackings.AddRange(from c in parent.Children
                               from gc in c.Children
                               let ch = gc.Children
                               select ch.Tracking);
            return trackings;
        }

        private IEnumerable<TrackingState> GetStates(Parent parent)
        {
            var trackings = new List<TrackingState>();
            trackings.AddRange(from c in parent.Children
                               select c.TrackingState);
            trackings.AddRange(from c in parent.Children
                               from gc in c.Children
                               select gc.TrackingState);
            trackings.AddRange(from c in parent.Children
                               from gc in c.Children
                               from ggc in gc.Children
                               select ggc.TrackingState);
            return trackings;
        }

        private IEnumerable<ICollection<string>> GetModifieds(Parent parent)
        {
            var modifieds = new List<ICollection<string>>();
            modifieds.AddRange(from c in parent.Children
                               select c.ModifiedProperties);
            modifieds.AddRange(from c in parent.Children
                               from gc in c.Children
                               select gc.ModifiedProperties);
            modifieds.AddRange(from c in parent.Children
                               from gc in c.Children
                               from ggc in gc.Children
                               select ggc.ModifiedProperties);
            return modifieds;
        }

        #endregion

        #region Helper Classes

        class Subscriber<TModel>
            where TModel : INotifyPropertyChanged
        {
            public TModel Model
            {
                set
                {
                    _model = value;
                    _model.PropertyChanged += OnPropertyChanged;
                }
            }
            private TModel _model;
            
            public bool ModelChanged { get; private set; }
            public string ChangedPropertyName { get; private set; }

            void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                ModelChanged = true;
                ChangedPropertyName = e.PropertyName;
            }
        }

        #endregion
    }
}


<|start_filename|>Source/TrackableEntities.EF.5/Constants.cs<|end_filename|>
﻿using System;

#if EF_6
namespace TrackableEntities.EF6
#else
namespace TrackableEntities.EF5
#endif
{
    internal static class Constants
    {
        public static class ExceptionMessages
        {
            public const string DeletedWithAddedChildren =
                "An entity may not be marked as Deleted if it has related entities which are marked as Added. " +
                "Remove added related entities before deleting a parent entity.";

            public const string RelationshipNotDetermined =
                "Cannot determine relationship type for {0} property on {1}.";
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample/WebApiSample.WebApi/Controllers/OrderController.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using TrackableEntities;
using TrackableEntities.Common;
using TrackableEntities.EF6;
using WebApiSample.Service.Entities.Contexts;
using WebApiSample.Service.Entities.Models;

namespace WebApiSample.Service.WebApi.Controllers
{
    public class OrderController : ApiController
    {
        private readonly NorthwindSlim _dbContext = new NorthwindSlim();

        // GET api/Order
        [ResponseType(typeof(IEnumerable<Order>))]
        public async Task<IHttpActionResult> GetOrders()
        {
	        IEnumerable<Order> orders = await _dbContext.Orders
				.Include(o => o.Customer)
                .Include("OrderDetails.Product") // Include details with products
                .ToListAsync();
	
            return Ok(orders);
        }

        // GET api/Order?customerId=ABCD
        [ResponseType(typeof(IEnumerable<Order>))]
        public async Task<IHttpActionResult> GetOrders(string customerId)
        {
            IEnumerable<Order> orders = await _dbContext.Orders
                .Include(o => o.Customer)
                .Include("OrderDetails.Product") // Include details with products
                .Where(o => o.CustomerId == customerId)
                .ToListAsync();

            return Ok(orders);
        }

        // GET api/Order/5
        [ResponseType(typeof(Order))]
        public async Task<IHttpActionResult> GetOrder(int id)
        {
	        Order order = await _dbContext.Orders
				.Include(o => o.Customer)
                .Include("OrderDetails.Product") // Include details with products
                .SingleOrDefaultAsync(o => o.OrderId == id);
	
            if (order == null)
            {
                return NotFound();
            }

            return Ok(order);
        }

        // POST api/Order
        [ResponseType(typeof(Order))]
        public async Task<IHttpActionResult> PostOrder(Order order)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            order.TrackingState = TrackingState.Added;
            _dbContext.ApplyChanges(order);

            await _dbContext.SaveChangesAsync();

            await _dbContext.LoadRelatedEntitiesAsync(order);
            order.AcceptChanges();
            return CreatedAtRoute("DefaultApi", new { id = order.OrderId }, order);
        }

        // PUT api/Order
        [ResponseType(typeof(Order))]
        public async Task<IHttpActionResult> PutOrder(Order order)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            _dbContext.ApplyChanges(order);

            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!_dbContext.Orders.Any(o => o.OrderId == order.OrderId))
                {
                    return Conflict();
                }
                throw;
            }

			await _dbContext.LoadRelatedEntitiesAsync(order);
			order.AcceptChanges();
	        return Ok(order);
        }

        // DELETE api/Order/5
        public async Task<IHttpActionResult> DeleteOrder(int id)
        {
			Order order = await _dbContext.Orders
                .Include(o => o.OrderDetails) // Include details
                .SingleOrDefaultAsync(o => o.OrderId == id);
			if (order == null)
            {
                return Ok();
            }

			order.TrackingState = TrackingState.Deleted;
			_dbContext.ApplyChanges(order);

            try
            {
	            await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!_dbContext.Orders.Any(o => o.OrderId == order.OrderId))
                {
                    return Conflict();
                }
                throw;
            }

            return Ok();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _dbContext.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}

<|start_filename|>Samples/VS2013/WcfSample/WcfSample.Service.Entities/Models/Product.cs<|end_filename|>
using System;
using System.Collections.Generic;
using TrackableEntities.Client;

namespace WcfSample.Client.Entities.Models
{
    public partial class Product : EntityBase
    {
		public Product()
		{
			this.OrderDetails = new ChangeTrackingCollection<OrderDetail>();
		}

		public int ProductId
		{ 
			get { return _ProductId; }
			set
			{
				if (Equals(value, _ProductId)) return;
				_ProductId = value;
				NotifyPropertyChanged();
			}
		}
		private int _ProductId;

		public string ProductName
		{ 
			get { return _ProductName; }
			set
			{
				if (Equals(value, _ProductName)) return;
				_ProductName = value;
				NotifyPropertyChanged();
			}
		}
		private string _ProductName;

		public Nullable<int> CategoryId
		{ 
			get { return _CategoryId; }
			set
			{
				if (Equals(value, _CategoryId)) return;
				_CategoryId = value;
				NotifyPropertyChanged();
			}
		}
		private Nullable<int> _CategoryId;

		public Nullable<decimal> UnitPrice
		{ 
			get { return _UnitPrice; }
			set
			{
				if (Equals(value, _UnitPrice)) return;
				_UnitPrice = value;
				NotifyPropertyChanged();
			}
		}
		private Nullable<decimal> _UnitPrice;

		public bool Discontinued
		{ 
			get { return _Discontinued; }
			set
			{
				if (Equals(value, _Discontinued)) return;
				_Discontinued = value;
				NotifyPropertyChanged();
			}
		}
		private bool _Discontinued;

		public byte[] RowVersion
		{ 
			get { return _RowVersion; }
			set
			{
				if (Equals(value, _RowVersion)) return;
				_RowVersion = value;
				NotifyPropertyChanged();
			}
		}
		private byte[] _RowVersion;

		public Category Category
		{
			get { return _Category; }
			set
			{
				if (Equals(value, _Category)) return;
				_Category = value;
				CategoryChangeTracker = _Category == null ? null
					: new ChangeTrackingCollection<Category> { _Category };
				NotifyPropertyChanged();
			}
		}
		private Category _Category;
		private ChangeTrackingCollection<Category> CategoryChangeTracker { get; set; }

		public ChangeTrackingCollection<OrderDetail> OrderDetails
		{
			get { return _OrderDetails; }
			set
			{
				if (Equals(value, _OrderDetails)) return;
				_OrderDetails = value;
				NotifyPropertyChanged();
			}
		}
		private ChangeTrackingCollection<OrderDetail> _OrderDetails;

	}
}


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm/WebApiSample.Mvvm.WebApi/Controllers/OrderController.cs<|end_filename|>
﻿using System;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Web.Http;
using System.Web.Http.Description;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using TrackableEntities;
using TrackableEntities.EF6;
using TrackableEntities.Common;
using WebApiSample.Mvvm.Service.Entities.Contexts;
using WebApiSample.Mvvm.Service.Entities.Models;

namespace WebApiSample.Mvvm.WebApi.Controllers
{
    public class OrderController : ApiController
    {
        private readonly NorthwindSlimContext _dbContext = new NorthwindSlimContext();

        // GET api/Order
        [ResponseType(typeof(IEnumerable<Order>))]
        public async Task<IHttpActionResult> GetOrders()
        {
            IEnumerable<Order> entities = await _dbContext.Orders
                .Include(e => e.Customer)
                .Include("OrderDetails.Product")
                .ToListAsync();

            return Ok(entities);
        }

        // GET api/Orders?customerId=ABCD
        public async Task<IEnumerable<Order>> GetOrders(string customerId)
        {
            IEnumerable<Order> orders = await _dbContext.Orders
                .Include(e => e.Customer)
                .Include("OrderDetails.Product")
                .Where(o => o.CustomerId == customerId)
                .OrderBy(e => e.OrderDate)
                .ToListAsync();
            return orders;
        }

        // GET api/Order/5
        [ResponseType(typeof(Order))]
        public async Task<IHttpActionResult> GetOrder(int id)
        {
            Order entity = await _dbContext.Orders
                .Include(e => e.Customer)
                .Include("OrderDetails.Product")
                .SingleOrDefaultAsync(e => e.OrderId == id);

            if (entity == null)
            {
                return NotFound();
            }

            return Ok(entity);
        }

        // POST api/Order
        [ResponseType(typeof(Order))]
        public async Task<IHttpActionResult> PostOrder(Order entity)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            entity.TrackingState = TrackingState.Added;
            _dbContext.ApplyChanges(entity);


            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateException)
            {
                if (_dbContext.Orders.Any(e => e.OrderId == entity.OrderId))
                {
                    return Conflict();
                }
                throw;
            }

            await _dbContext.LoadRelatedEntitiesAsync(entity);
            entity.AcceptChanges();
            return CreatedAtRoute("DefaultApi", new { id = entity.OrderId }, entity);
        }

        // PUT api/Order
        [ResponseType(typeof(Order))]
        public async Task<IHttpActionResult> PutOrder(Order entity)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            _dbContext.ApplyChanges(entity);

            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!_dbContext.Orders.Any(e => e.OrderId == entity.OrderId))
                {
                    return Conflict();
                }
                throw;
            }

            await _dbContext.LoadRelatedEntitiesAsync(entity);
            entity.AcceptChanges();
            return Ok(entity);
        }

        // DELETE api/Order/5
        public async Task<IHttpActionResult> DeleteOrder(int id)
        {
            Order entity = await _dbContext.Orders
                .Include(e => e.OrderDetails)
                .SingleOrDefaultAsync(e => e.OrderId == id);
            if (entity == null)
            {
                return Ok();
            }

            entity.TrackingState = TrackingState.Deleted;
            _dbContext.ApplyChanges(entity);

            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!_dbContext.Orders.Any(e => e.OrderId == entity.OrderId))
                {
                    return Conflict();
                }
                throw;
            }

            return Ok();
        }

        protected override void Dispose(bool disposing)
        {
            _dbContext.Dispose();
            base.Dispose(disposing);
        }
    }
}


<|start_filename|>Source/Tests/TrackableEntities.Client.Tests.Entities/NorthwindModels/Area.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace TrackableEntities.Client.Tests.Entities.NorthwindModels
{
    [JsonObject(IsReference = true)]
    public class Area : EntityBase
    {
        private int _areaId;
        public int AreaId
        {
            get { return _areaId; }
            set
            {
                if (value == _areaId) return;
                _areaId = value;
                NotifyPropertyChanged(() => AreaId);
            }
        }

        private string _areaName;
        public string AreaName
        {
            get { return _areaName; }
            set
            {
                if (value == _areaName) return;
                _areaName = value;
                NotifyPropertyChanged(() => AreaName);
            }
        }

        private ChangeTrackingCollection<Territory> _territories;
        public ChangeTrackingCollection<Territory> Territories
        {
            get { return _territories; }
            set
            {
                if (Equals(value, _territories)) return;
                _territories = value;
                NotifyPropertyChanged(() => Territories);
            }
        }
    }
}


<|start_filename|>Source/TrackableEntities.EF.5/IStateInterceptor.cs<|end_filename|>
using System.Data.Entity;
#if EF_6
#else
using System.Data;
#endif

#if EF_6
namespace TrackableEntities.EF6
#else
namespace TrackableEntities.EF5
#endif
{
    /// <summary>
    /// Interface implemented by interceptors added to <see cref="DbContextExtensions.ApplyChanges(DbContext,ITrackable)"/>.
    /// </summary>
    public interface IStateInterceptor
    {
        /// <summary>
        /// Gets state of <paramref name="item"/> based on <paramref name="relationshipType"/>.
        /// </summary>
        /// <param name="item">Current item.</param>
        /// <param name="relationshipType">Relationship of current item.</param>
        /// <returns>State of <paramref name="item"/> based on <paramref name="relationshipType"/>.</returns>
        EntityState? GetEntityState(ITrackable item, RelationshipType? relationshipType);
    }
}

<|start_filename|>Extensions/Common/Wizards/TrackableEntities.ItemWizard/Dialogs.cs<|end_filename|>
﻿using System;

namespace TrackableEntities.ItemWizard
{
    public static class Dialogs
    {
        public static class WcfServiceType
        {
            public const string Title = "Trackable WCF Service Type";
            public const string Message = "Add a WCF Service Type with read-write operations using Trackable Entities.";
            public const bool GetDbContextName = true;
            public const int DialogWidth = 650;
        }

        public static class WebApiController
        {
            public const string Title = "Entity Web API Controller";
            public const string Message = "Add an Entity Web API Controller to the WebApi project.";
            public const bool GetDbContextName = true;
            public const int DialogWidth = 550;
        }

        public static class EntityController
        {
            public const string Title = "Entity Web API Controller";
            public const string Message = "Add an Entity Web API Controller to the Patterns WebApi project.";
            public const bool GetDbContextName = false;
            public const int DialogWidth = 550;
        }

        public static class EntityRepoClass
        {
            public const string Title = "Entity Repository Class";
            public const string Message = "Add an Entity Repository Class to the Patterns EF project.";
            public const bool GetDbContextName = false;
            public const int DialogWidth = 600;
        }

        public static class EntityRepoInterface
        {
            public const string Title = "Entity Repository Interface";
            public const string Message = "Add an Entity Repository Interface to the Patterns Persistence project.";
            public const bool GetDbContextName = false;
            public const int DialogWidth = 650;
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.ModelFirst/WebApiSample.Service.Entities/Product.cs<|end_filename|>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace WebApiSample.Service.Entities
{
    using System;
    using System.Collections.Generic;
    using TrackableEntities;
    
    public partial class Product : ITrackable, IMergeable
    {
        public Product()
        {
            this.OrderDetails = new List<OrderDetail>();
        }
    
        public int ProductId { get; set; }
        public string ProductName { get; set; }
        public Nullable<int> CategoryId { get; set; }
        public Nullable<decimal> UnitPrice { get; set; }
        public bool Discontinued { get; set; }
        public byte[] RowVersion { get; set; }
    
        public Category Category { get; set; }
        public ICollection<OrderDetail> OrderDetails { get; set; }
    
        public TrackingState TrackingState { get; set; }
        public ICollection<string> ModifiedProperties { get; set; }
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Samples/VS2012/WebApiSample/WebApiSample.Client.Entities/Models/Customer.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using TrackableEntities;
using TrackableEntities.Client;

namespace WebApiSample.Client.Entities.Models
{
    [JsonObject(IsReference = true)]
    [DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
    public partial class Customer : ModelBase<Customer>, IEquatable<Customer>, ITrackable
    {
		public Customer()
		{
			this.Orders = new ChangeTrackingCollection<Order>();
		}

		[DataMember]
		public string CustomerId
		{ 
			get { return _CustomerId; }
			set
			{
				if (Equals(value, _CustomerId)) return;
				_CustomerId = value;
				NotifyPropertyChanged(m => m.CustomerId);
			}
		}
		private string _CustomerId;

		[DataMember]
		public string CompanyName
		{ 
			get { return _CompanyName; }
			set
			{
				if (Equals(value, _CompanyName)) return;
				_CompanyName = value;
				NotifyPropertyChanged(m => m.CompanyName);
			}
		}
		private string _CompanyName;

		[DataMember]
		public string ContactName
		{ 
			get { return _ContactName; }
			set
			{
				if (Equals(value, _ContactName)) return;
				_ContactName = value;
				NotifyPropertyChanged(m => m.ContactName);
			}
		}
		private string _ContactName;

		[DataMember]
		public string City
		{ 
			get { return _City; }
			set
			{
				if (Equals(value, _City)) return;
				_City = value;
				NotifyPropertyChanged(m => m.City);
			}
		}
		private string _City;

		[DataMember]
		public string Country
		{ 
			get { return _Country; }
			set
			{
				if (Equals(value, _Country)) return;
				_Country = value;
				NotifyPropertyChanged(m => m.Country);
			}
		}
		private string _Country;

		[DataMember]
		public CustomerSetting CustomerSetting
		{
			get { return _CustomerSetting; }
			set
			{
				if (Equals(value, _CustomerSetting)) return;
				_CustomerSetting = value;
				CustomerSettingChangeTracker = _CustomerSetting == null ? null
					: new ChangeTrackingCollection<CustomerSetting> { _CustomerSetting };
				NotifyPropertyChanged(m => m.CustomerSetting);
			}
		}
		private CustomerSetting _CustomerSetting;
		private ChangeTrackingCollection<CustomerSetting> CustomerSettingChangeTracker { get; set; }

		[DataMember]
		public ChangeTrackingCollection<Order> Orders
		{
			get { return _Orders; }
			set
			{
				if (Equals(value, _Orders)) return;
				_Orders = value;
				NotifyPropertyChanged(m => m.Orders);
			}
		}
		private ChangeTrackingCollection<Order> _Orders;

        #region Change Tracking

		[DataMember]
		public TrackingState TrackingState { get; set; }

		[DataMember]
		public ICollection<string> ModifiedProperties { get; set; }

		[JsonProperty, DataMember]
		private Guid EntityIdentifier { get; set; }

		#pragma warning disable 414

		[JsonProperty, DataMember]
		private Guid _entityIdentity = default(Guid);

		#pragma warning restore 414

		bool IEquatable<Customer>.Equals(Customer other)
		{
			if (EntityIdentifier != default(Guid))
				return EntityIdentifier == other.EntityIdentifier;
			return false;
		}
        #endregion
	}
}


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm/WebApiSample.Mvvm.Service.Entities/Models/OrderDetail.cs<|end_filename|>
using System;
using System.Collections.Generic;
using TrackableEntities;

namespace WebApiSample.Mvvm.Service.Entities.Models
{
    public partial class OrderDetail : ITrackable, IMergeable
    {
        public int OrderDetailId { get; set; }
        public int OrderId { get; set; }
        public int ProductId { get; set; }
        public decimal UnitPrice { get; set; }
        public short Quantity { get; set; }
        public float Discount { get; set; }
        public Order Order { get; set; }
        public Product Product { get; set; }

        public TrackingState TrackingState { get; set; }
        public ICollection<string> ModifiedProperties { get; set; }
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Source/TrackableEntities.EF.5/StateChangeInterceptor.cs<|end_filename|>
using System;
#if EF_6
using System.Data.Entity;
#else
using System.Data;
#endif

#if EF_6
namespace TrackableEntities.EF6
#else
namespace TrackableEntities.EF5
#endif
{
    /// <summary>
    /// Interceptor for setting explicitly the state of an entity.
    /// </summary>
    /// <typeparam name="TEntity">Type of entity.</typeparam>
    public class StateChangeInterceptor<TEntity> : IStateInterceptor where TEntity : class, ITrackable
    {
        private readonly Func<TEntity, RelationshipType?, EntityState?> _selector;

        /// <summary>
        /// Initializes a new instance of the <see cref="T:StateChangeInterceptor"/> class.
        /// </summary>
        public StateChangeInterceptor(Func<TEntity, RelationshipType?, EntityState?> selector)
        {
            _selector = selector;
        }

        /// <summary>
        /// Gets state of <paramref name="item"/> based on <paramref name="relationshipType"/>.
        /// </summary>
        /// <param name="item">Current item.</param>
        /// <param name="relationshipType">Relationship of current item.</param>
        /// <returns>State of <paramref name="item"/> based on <paramref name="relationshipType"/>.</returns>
        public EntityState? GetEntityState(ITrackable item, RelationshipType? relationshipType)
        {
            var entity = item as TEntity;
            return entity != null ? _selector(entity, relationshipType) : null;
        }
    }
}

<|start_filename|>Build/Scripts/Debug/TrackableEntities.Common-test.cmd<|end_filename|>
cd ..\..\..\
set PackageVersion=2.5.0-test
set Configuration=Debug
rem pass 1 to debug, 0 to run without pausing
Build\Scripts\TrackableEntities.Common.cmd 1


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm/WebApiSample.Mvvm.Client.Entities/Models/Order.cs<|end_filename|>
using System;
using System.Collections.Generic;
using TrackableEntities.Client;

namespace WebApiSample.Mvvm.Client.Entities.Models
{
    public partial class Order : EntityBase
    {
		public Order()
		{
			this.OrderDetails = new ChangeTrackingCollection<OrderDetail>();
		}

		public int OrderId
		{ 
			get { return _OrderId; }
			set
			{
				if (Equals(value, _OrderId)) return;
				_OrderId = value;
				NotifyPropertyChanged(() => OrderId);
			}
		}
		private int _OrderId;

		public string CustomerId
		{ 
			get { return _CustomerId; }
			set
			{
				if (Equals(value, _CustomerId)) return;
				_CustomerId = value;
				NotifyPropertyChanged(() => CustomerId);
			}
		}
		private string _CustomerId;

		public Nullable<System.DateTime> OrderDate
		{ 
			get { return _OrderDate; }
			set
			{
				if (Equals(value, _OrderDate)) return;
				_OrderDate = value;
				NotifyPropertyChanged(() => OrderDate);
			}
		}
		private Nullable<System.DateTime> _OrderDate;

		public Nullable<System.DateTime> ShippedDate
		{ 
			get { return _ShippedDate; }
			set
			{
				if (Equals(value, _ShippedDate)) return;
				_ShippedDate = value;
				NotifyPropertyChanged(() => ShippedDate);
			}
		}
		private Nullable<System.DateTime> _ShippedDate;

		public Nullable<int> ShipVia
		{ 
			get { return _ShipVia; }
			set
			{
				if (Equals(value, _ShipVia)) return;
				_ShipVia = value;
				NotifyPropertyChanged(() => ShipVia);
			}
		}
		private Nullable<int> _ShipVia;

		public Nullable<decimal> Freight
		{ 
			get { return _Freight; }
			set
			{
				if (Equals(value, _Freight)) return;
				_Freight = value;
				NotifyPropertyChanged(() => Freight);
			}
		}
		private Nullable<decimal> _Freight;

		public Customer Customer
		{
			get { return _Customer; }
			set
			{
				if (Equals(value, _Customer)) return;
				_Customer = value;
				CustomerChangeTracker = _Customer == null ? null
					: new ChangeTrackingCollection<Customer> { _Customer };
				NotifyPropertyChanged(() => Customer);
			}
		}
		private Customer _Customer;
		private ChangeTrackingCollection<Customer> CustomerChangeTracker { get; set; }

		public ChangeTrackingCollection<OrderDetail> OrderDetails
		{
			get { return _OrderDetails; }
			set
			{
				if (Equals(value, _OrderDetails)) return;
				_OrderDetails = value;
				NotifyPropertyChanged(() => OrderDetails);
			}
		}
		private ChangeTrackingCollection<OrderDetail> _OrderDetails;

	}
}


<|start_filename|>Samples/VS2012/WcfSample/WcfSample.Client.Entities/Models/Product.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using TrackableEntities;
using TrackableEntities.Client;

namespace WcfSample.Client.Entities.Models
{
    [JsonObject(IsReference = true)]
    [DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
    public partial class Product : ModelBase<Product>, IEquatable<Product>, ITrackable
    {
		public Product()
		{
			this.OrderDetails = new ChangeTrackingCollection<OrderDetail>();
		}

		[DataMember]
		public int ProductId
		{ 
			get { return _ProductId; }
			set
			{
				if (Equals(value, _ProductId)) return;
				_ProductId = value;
				NotifyPropertyChanged(m => m.ProductId);
			}
		}
		private int _ProductId;

		[DataMember]
		public string ProductName
		{ 
			get { return _ProductName; }
			set
			{
				if (Equals(value, _ProductName)) return;
				_ProductName = value;
				NotifyPropertyChanged(m => m.ProductName);
			}
		}
		private string _ProductName;

		[DataMember]
		public Nullable<int> CategoryId
		{ 
			get { return _CategoryId; }
			set
			{
				if (Equals(value, _CategoryId)) return;
				_CategoryId = value;
				NotifyPropertyChanged(m => m.CategoryId);
			}
		}
		private Nullable<int> _CategoryId;

		[DataMember]
		public Nullable<decimal> UnitPrice
		{ 
			get { return _UnitPrice; }
			set
			{
				if (Equals(value, _UnitPrice)) return;
				_UnitPrice = value;
				NotifyPropertyChanged(m => m.UnitPrice);
			}
		}
		private Nullable<decimal> _UnitPrice;

		[DataMember]
		public bool Discontinued
		{ 
			get { return _Discontinued; }
			set
			{
				if (Equals(value, _Discontinued)) return;
				_Discontinued = value;
				NotifyPropertyChanged(m => m.Discontinued);
			}
		}
		private bool _Discontinued;

		[DataMember]
		public byte[] RowVersion
		{ 
			get { return _RowVersion; }
			set
			{
				if (Equals(value, _RowVersion)) return;
				_RowVersion = value;
				NotifyPropertyChanged(m => m.RowVersion);
			}
		}
		private byte[] _RowVersion;

		[DataMember]
		public Category Category
		{
			get { return _Category; }
			set
			{
				if (Equals(value, _Category)) return;
				_Category = value;
				CategoryChangeTracker = _Category == null ? null
					: new ChangeTrackingCollection<Category> { _Category };
				NotifyPropertyChanged(m => m.Category);
			}
		}
		private Category _Category;
		private ChangeTrackingCollection<Category> CategoryChangeTracker { get; set; }

		[DataMember]
		public ChangeTrackingCollection<OrderDetail> OrderDetails
		{
			get { return _OrderDetails; }
			set
			{
				if (Equals(value, _OrderDetails)) return;
				_OrderDetails = value;
				NotifyPropertyChanged(m => m.OrderDetails);
			}
		}
		private ChangeTrackingCollection<OrderDetail> _OrderDetails;

        #region Change Tracking

		[DataMember]
		public TrackingState TrackingState { get; set; }

		[DataMember]
		public ICollection<string> ModifiedProperties { get; set; }

		[JsonProperty, DataMember]
		private Guid EntityIdentifier { get; set; }

		#pragma warning disable 414

		[JsonProperty, DataMember]
		private Guid _entityIdentity = default(Guid);

		#pragma warning restore 414

		bool IEquatable<Product>.Equals(Product other)
		{
			if (EntityIdentifier != default(Guid))
				return EntityIdentifier == other.EntityIdentifier;
			return false;
		}
        #endregion
	}
}


<|start_filename|>Samples/VS2013/WebApiSample/WebApiSample.Service.Entities/Models/Territory.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using TrackableEntities;

namespace WebApiSample.Service.Entities.Models
{
    [Table("Territory")]
    public partial class Territory : ITrackable, IMergeable
    {
        public Territory()
        {
            Employees = new List<Employee>();
        }

        [StringLength(20)]
        public string TerritoryId { get; set; }

        [Required]
        [StringLength(50)]
        public string TerritoryDescription { get; set; }

        public ICollection<Employee> Employees { get; set; }

		[NotMapped]
        public TrackingState TrackingState { get; set; }

		[NotMapped]
        public ICollection<string> ModifiedProperties { get; set; }

		[NotMapped]
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Patterns/WebApiSample.Service.EF/Mapping/CategoryMap.cs<|end_filename|>
using System.Data.Entity.ModelConfiguration;
using WebApiSample.Service.Entities.Models;

namespace WebApiSample.Service.EF.Mapping
{
    public class CategoryMap : EntityTypeConfiguration<Category>
    {
        public CategoryMap()
        {
            // Primary Key
            this.HasKey(t => t.CategoryId);

            // Properties
            this.Property(t => t.CategoryName)
                .IsRequired()
                .HasMaxLength(15);

            // Table & Column Mappings
            this.ToTable("Category");
            this.Property(t => t.CategoryId).HasColumnName("CategoryId");
            this.Property(t => t.CategoryName).HasColumnName("CategoryName");

            // Tracking Properties
			this.Ignore(t => t.TrackingState);
			this.Ignore(t => t.ModifiedProperties);
			this.Ignore(t => t.EntityIdentifier);
        }
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/Helpers/EntityExtensions.cs<|end_filename|>
﻿using System;
using TrackableEntities.Client;
using TrackableEntities.EF.Tests.NorthwindModels;

namespace TrackableEntities.Tests.Acceptance.Helpers
{
    internal static class EntityExtensions
    {
        public static ClientEntities.Category ToClientEntity(this Category category)
        {
            if (category == null) return null;
            return new ClientEntities.Category
            {
                CategoryId = category.CategoryId,
                CategoryName = category.CategoryName
            };
        }

        public static ClientEntities.Product ToClientEntity(this Product product)
        {
            if (product == null) return null;
            return new ClientEntities.Product
            {
                ProductId = product.ProductId,
                ProductName = product.ProductName,
                UnitPrice = product.UnitPrice,
                CategoryId = product.CategoryId,
                Category = product.Category.ToClientEntity()
            };
        }

        public static ClientEntities.CustomerSetting ToClientEntity(this CustomerSetting setting)
        {
            if (setting == null) return null;
            return new ClientEntities.CustomerSetting
            {
                CustomerId = setting.CustomerId,
                Setting = setting.Setting
            };
        }

        public static ClientEntities.Customer ToClientEntity(this Customer customer)
        {
            if (customer == null) return null;
            return new ClientEntities.Customer
            {
                CustomerId = customer.CustomerId,
                CustomerName = customer.CustomerName,
                CustomerSetting = customer.CustomerSetting.ToClientEntity()
            };
        }

        public static ClientEntities.OrderDetail ToClientEntity(this OrderDetail detail, ClientEntities.Order order)
        {
            if (detail == null) return null;
            return new ClientEntities.OrderDetail
            {
                OrderDetailId = detail.OrderDetailId,
                OrderId = detail.OrderId,
                ProductId = detail.ProductId,
                Quantity = detail.Quantity,
                UnitPrice = detail.UnitPrice,
                Order = order
            };
        }

        public static ClientEntities.Order ToClientEntity(this Order order)
        {
            if (order == null) return null;
            var clientOrder = new ClientEntities.Order
            {
                OrderId = order.OrderId,
                OrderDate = order.OrderDate,
                CustomerId = order.CustomerId,
                Customer = order.Customer.ToClientEntity()
            };
            if (order.OrderDetails != null)
            {
                clientOrder.OrderDetails = new ChangeTrackingCollection<ClientEntities.OrderDetail>();
                foreach (var detail in order.OrderDetails)
                {
                    if (detail != null)
                        clientOrder.OrderDetails.Add(detail.ToClientEntity(clientOrder));
                }
            }
            return clientOrder;
        }

        public static ClientEntities.Order CreateNewOrder(string customerId, int[] productIds)
        {
            var clientOrder = new ClientEntities.Order
            {
                CustomerId = customerId,
                OrderDate = DateTime.Today, 
                OrderDetails = new ChangeTrackingCollection<ClientEntities.OrderDetail>
                    {
                        new ClientEntities.OrderDetail { ProductId = productIds[0], Quantity = 5, UnitPrice = 10 },
                        new ClientEntities.OrderDetail { ProductId = productIds[1], Quantity = 10, UnitPrice = 20 },
                        new ClientEntities.OrderDetail { ProductId = productIds[2], Quantity = 40, UnitPrice = 40 }
                    }
            };
            return clientOrder;
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.ModelFirst/WebApiSample.Service.Entities/OrderDetail.cs<|end_filename|>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace WebApiSample.Service.Entities
{
    using System;
    using System.Collections.Generic;
    using TrackableEntities;
    
    public partial class OrderDetail : ITrackable, IMergeable
    {
        public int OrderDetailId { get; set; }
        public int OrderId { get; set; }
        public int ProductId { get; set; }
        public decimal UnitPrice { get; set; }
        public short Quantity { get; set; }
        public float Discount { get; set; }
    
        public Order Order { get; set; }
        public Product Product { get; set; }
    
        public TrackingState TrackingState { get; set; }
        public ICollection<string> ModifiedProperties { get; set; }
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Source/TrackableEntities.Client/Constants.cs<|end_filename|>
﻿using System;

namespace TrackableEntities.Client
{
    /// <summary>
    /// TrackableEntities constants.
    /// </summary>
    internal static class Constants
    {
        /// <summary>
        /// Change-tracking property names.
        /// </summary>
        public static class TrackingProperties
        {
            /// <summary>TrackingState property name</summary>
            public const string TrackingState = "TrackingState";
            /// <summary>ModifiedProperties property name</summary>
            public const string ModifiedProperties = "ModifiedProperties";
        }

        /// <summary>
        /// Change-tracking member names.
        /// </summary>
        public static class ChangeTrackingMembers
        {
            /// <summary>Change-tracking property end</summary>
            public const string ChangeTrackingPropEnd = "ChangeTracker";
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Patterns/WebApiSample.Service.EF/Repositories/OrderRepository.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using TrackableEntities;
using TrackableEntities.Patterns.EF6;
using WebApiSample.Service.EF.Contexts;
using WebApiSample.Service.Entities.Models;
using WebApiSample.Service.Persistence.Repositories;

namespace WebApiSample.Service.EF.Repositories
{
    public class OrderRepository : Repository<Order>, IOrderRepository
    {
        private readonly INorthwindSlimContext _context;

        public OrderRepository(INorthwindSlimContext context) : 
            base(context as DbContext)
        {
            _context = context;
        }

        public async Task<IEnumerable<Order>> GetOrders()
        {
            IEnumerable<Order> orders = await _context.Orders
                .Include(o => o.Customer)
                .Include("OrderDetails.Product")
                .ToListAsync();
            return orders;
        }

        public async Task<IEnumerable<Order>> GetOrders(string customerId)
        {
            IEnumerable<Order> orders = await _context.Orders
                .Include(o => o.Customer)
                .Include("OrderDetails.Product")
                .Where(o => o.CustomerId == customerId)
                .ToListAsync();
            return orders;
        }

        public async Task<Order> GetOrder(int id)
        {
            Order order = await _context.Orders
                 .Include(o => o.Customer)
                 .Include("OrderDetails.Product")
                 .SingleOrDefaultAsync(o => o.OrderId == id);
            return order;
        }

        public async Task<bool> DeleteOrder(int id)
        {
            Order order = await _context.Orders
                .Include(o => o.OrderDetails) // Include details
                .SingleOrDefaultAsync(o => o.OrderId == id);
            ApplyDelete(order);
            return true;
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Patterns/WebApiSample.Service.Persistence/UnitsOfWork/INorthwindUnitOfWork.cs<|end_filename|>
﻿using System;
using TrackableEntities.Patterns;
using WebApiSample.Service.Persistence.Repositories;

namespace WebApiSample.Service.Persistence.UnitsOfWork
{
    public interface INorthwindUnitOfWork : IUnitOfWork, IUnitOfWorkAsync
    {
        ICustomerRepository CustomerRepository { get; }
        IOrderRepository OrderRepository { get; }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.ModelFirst/WebApiSample.Service.Entities/Territory.cs<|end_filename|>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace WebApiSample.Service.Entities
{
    using System;
    using System.Collections.Generic;
    using TrackableEntities;
    
    public partial class Territory : ITrackable, IMergeable
    {
        public Territory()
        {
            this.Employees = new List<Employee>();
        }
    
        public string TerritoryId { get; set; }
        public string TerritoryDescription { get; set; }
    
        public ICollection<Employee> Employees { get; set; }
    
        public TrackingState TrackingState { get; set; }
        public ICollection<string> ModifiedProperties { get; set; }
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Samples/VS2013/WcfSample/WcfSample.Shared.Entities.Net45/Contexts/NorthwindSlim.Mappings.cs<|end_filename|>
﻿using System.Data.Entity;
using WcfSample.Shared.Entities.Net45.Models;

namespace WcfSample.Shared.Entities.Net45.Contexts
{
    public partial class NorthwindSlim
    {
        partial void ModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<CustomerSetting>()
                .HasKey(e => e.CustomerId);
        }
    }
}


<|start_filename|>Samples/VS2012/WcfSample/WcfSample.Client.Entities/Models/CustomerSetting.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using TrackableEntities;
using TrackableEntities.Client;

namespace WcfSample.Client.Entities.Models
{
    [JsonObject(IsReference = true)]
    [DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
    public partial class CustomerSetting : ModelBase<CustomerSetting>, IEquatable<CustomerSetting>, ITrackable
    {
		[DataMember]
		public string CustomerId
		{ 
			get { return _CustomerId; }
			set
			{
				if (Equals(value, _CustomerId)) return;
				_CustomerId = value;
				NotifyPropertyChanged(m => m.CustomerId);
			}
		}
		private string _CustomerId;

		[DataMember]
		public string Setting
		{ 
			get { return _Setting; }
			set
			{
				if (Equals(value, _Setting)) return;
				_Setting = value;
				NotifyPropertyChanged(m => m.Setting);
			}
		}
		private string _Setting;

		[DataMember]
		public Customer Customer
		{
			get { return _Customer; }
			set
			{
				if (Equals(value, _Customer)) return;
				_Customer = value;
				CustomerChangeTracker = _Customer == null ? null
					: new ChangeTrackingCollection<Customer> { _Customer };
				NotifyPropertyChanged(m => m.Customer);
			}
		}
		private Customer _Customer;
		private ChangeTrackingCollection<Customer> CustomerChangeTracker { get; set; }

        #region Change Tracking

		[DataMember]
		public TrackingState TrackingState { get; set; }

		[DataMember]
		public ICollection<string> ModifiedProperties { get; set; }

		[JsonProperty, DataMember]
		private Guid EntityIdentifier { get; set; }

		#pragma warning disable 414

		[JsonProperty, DataMember]
		private Guid _entityIdentity = default(Guid);

		#pragma warning restore 414

		bool IEquatable<CustomerSetting>.Equals(CustomerSetting other)
		{
			if (EntityIdentifier != default(Guid))
				return EntityIdentifier == other.EntityIdentifier;
			return false;
		}
        #endregion
	}
}


<|start_filename|>Samples/VS2013/WebApiSample.Patterns/WebApiSample.Service.EF/Repositories/CustomerRepository.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Threading.Tasks;
using TrackableEntities.Patterns.EF6;
using WebApiSample.Service.EF.Contexts;
using WebApiSample.Service.Entities.Models;
using WebApiSample.Service.Persistence.Repositories;

namespace WebApiSample.Service.EF.Repositories
{
    public class CustomerRepository : Repository<Customer>, ICustomerRepository
    {
        private readonly INorthwindSlimContext _context;

        public CustomerRepository(INorthwindSlimContext context) :
            base(context as DbContext)
        {
            _context = context;
        }

        public async Task<Customer> GetCustomer(string id)
        {
            Customer customer = await FindAsync(id);
            return customer;
        }

        public async Task<IEnumerable<Customer>> GetCustomers()
        {
            IEnumerable<Customer> customers = await _context.Customers.ToListAsync();
            return customers;
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm.WpfClient/Constants.cs<|end_filename|>
﻿using System;

namespace WebApiSample.Mvvm.WpfClient
{
    internal static class Constants
    {
        public static class WebClient
        {
            public const int PortNumber = 49580;
            public const string ServiceHost = "localhost";
        }
    }
}


<|start_filename|>Samples/VS2013/WcfSample/WcfSample.ConsoleClient/ICustomerService.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Threading.Tasks;
using WcfSample.Shared.Entities.Net45.Models;

namespace WcfSample.Client.ConsoleApp
{
    [ServiceContract(Namespace = "urn:trackable-entities:samples")]
    public interface ICustomerService
    {
        [OperationContract(Name = "GetCustomers")]
        Task<IEnumerable<Customer>> GetCustomersAsync();

        [OperationContract(Name = "GetCustomer")]
        Task<Customer> GetCustomerAsync(string id);

        [OperationContract(Name = "UpdateCustomer")]
        Task<Customer> UpdateCustomerAsync(Customer customer);

        [OperationContract(Name = "CreateCustomer")]
        Task<Customer> CreateCustomerAsync(Customer customer);

        [OperationContract(Name = "DeleteCustomer")]
        Task DeleteCustomerAsync(string id);
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/ClientEntities/OrderDetail.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using TrackableEntities.Client;

namespace TrackableEntities.Tests.Acceptance.ClientEntities
{
    [JsonObject(IsReference = true)]
    public class OrderDetail : EntityBase
    {
        private int _orderDetailId;
        public int OrderDetailId
        {
            get { return _orderDetailId; }
            set
            {
                if (value == _orderDetailId) return;
                _orderDetailId = value;
                NotifyPropertyChanged();
            }
        }

        private int _productId;
        public int ProductId
        {
            get { return _productId; }
            set
            {
                if (value == _productId) return;
                _productId = value;
                NotifyPropertyChanged();
            }
        }

        private int _orderId;
        public int OrderId
        {
            get { return _orderId; }
            set
            {
                if (value == _orderId) return;
                _orderId = value;
                NotifyPropertyChanged();
            }
        }

        private Product _product;
        public Product Product
        {
            get { return _product; }
            set
            {
                if (value == _product) return;
                _product = value;
                ProductChangeTracker = _product == null ? null
                    : new ChangeTrackingCollection<Product> { _product };
                NotifyPropertyChanged();
            }
        }
        private ChangeTrackingCollection<Product> ProductChangeTracker { get; set; }

        private Order _order;
        public Order Order
        {
            get { return _order; }
            set
            {
                if (value == _order) return;
                _order = value;
                NotifyPropertyChanged();
            }
        }

        private decimal _unitPrice;
        public decimal UnitPrice
        {
            get { return _unitPrice; }
            set
            {
                if (value == _unitPrice) return;
                _unitPrice = value;
                NotifyPropertyChanged();
            }
        }

        private double _quanity;
        public double Quantity
        {
            get { return _quanity; }
            set
            {
                if (Math.Abs(value - _quanity) < double.Epsilon) return;
                _quanity = value;
                NotifyPropertyChanged();
            }
        }
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/Features/OneToOneRelations.feature.cs<|end_filename|>
﻿// ------------------------------------------------------------------------------
//  <auto-generated>
//      This code was generated by SpecFlow (http://www.specflow.org/).
//      SpecFlow Version:1.9.0.77
//      SpecFlow Generator Version:1.9.0.0
//      Runtime Version:4.0.30319.34209
// 
//      Changes to this file may cause incorrect behavior and will be lost if
//      the code is regenerated.
//  </auto-generated>
// ------------------------------------------------------------------------------
#region Designer generated code
#pragma warning disable
namespace TrackableEntities.Tests.Acceptance.Features
{
    using TechTalk.SpecFlow;
    
    
    [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.9.0.77")]
    [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    public partial class OneToOneRelationsFeature : Xunit.IUseFixture<OneToOneRelationsFeature.FixtureData>, System.IDisposable
    {
        
        private static TechTalk.SpecFlow.ITestRunner testRunner;
        
#line 1 "OneToOneRelations.feature"
#line hidden
        
        public OneToOneRelationsFeature()
        {
            this.TestInitialize();
        }
        
        public static void FeatureSetup()
        {
            testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner();
            TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "OneToOne Relations", "In order to update entity relations\r\nAs a Web API client\r\nI want to save one-to-o" +
                    "ne relations to the database", ProgrammingLanguage.CSharp, ((string[])(null)));
            testRunner.OnFeatureStart(featureInfo);
        }
        
        public static void FeatureTearDown()
        {
            testRunner.OnFeatureEnd();
            testRunner = null;
        }
        
        public virtual void TestInitialize()
        {
        }
        
        public virtual void ScenarioTearDown()
        {
            testRunner.OnScenarioEnd();
        }
        
        public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo)
        {
            testRunner.OnScenarioStart(scenarioInfo);
        }
        
        public virtual void ScenarioCleanup()
        {
            testRunner.CollectScenarioErrors();
        }
        
        public virtual void SetFixture(OneToOneRelationsFeature.FixtureData fixtureData)
        {
        }
        
        void System.IDisposable.Dispose()
        {
            this.ScenarioTearDown();
        }
        
        [Xunit.FactAttribute(Skip="Ignored")]
        [Xunit.TraitAttribute("FeatureTitle", "OneToOne Relations")]
        [Xunit.TraitAttribute("Description", "Create Customer Setting")]
        public virtual void CreateCustomerSetting()
        {
            TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Create Customer Setting", new string[] {
                        "ignore",
                        "entity_relations"});
#line 7
this.ScenarioSetup(scenarioInfo);
#line hidden
            TechTalk.SpecFlow.Table table1 = new TechTalk.SpecFlow.Table(new string[] {
                        "CustomerId",
                        "CustomerName"});
            table1.AddRow(new string[] {
                        "IJKL",
                        "Acme Company"});
#line 8
 testRunner.Given("the following new customer", ((string)(null)), table1, "Given ");
#line 11
 testRunner.When("I submit a POST to create a customer", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line 12
 testRunner.And("I add a customer setting", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
#line 13
 testRunner.And("I submit a PUT to update the customer", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
#line 14
 testRunner.Then("the request should return the new customer", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
            this.ScenarioCleanup();
        }
        
        [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.9.0.77")]
        [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
        public class FixtureData : System.IDisposable
        {
            
            public FixtureData()
            {
                OneToOneRelationsFeature.FeatureSetup();
            }
            
            void System.IDisposable.Dispose()
            {
                OneToOneRelationsFeature.FeatureTearDown();
            }
        }
    }
}
#pragma warning restore
#endregion


<|start_filename|>Samples/VS2013/WebApiSample.Patterns/WebApiSample.Service.Persistence/Exceptions/UpdateException.cs<|end_filename|>
﻿using System;

namespace WebApiSample.Service.Persistence.Exceptions
{
    public class UpdateException : Exception
    {
        public UpdateException()
        {
        }

        public UpdateException(string message) : base(message)
        {
        }

        public UpdateException(string message, Exception inner) : base(message, inner)
        {
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Mvvm/WebApiSample.Mvvm/WebApiSample.Mvvm.Client.Entities/Models/OrderDetail.cs<|end_filename|>
using System;
using System.Collections.Generic;
using TrackableEntities.Client;

namespace WebApiSample.Mvvm.Client.Entities.Models
{
    public partial class OrderDetail : EntityBase
    {
		public int OrderDetailId
		{ 
			get { return _OrderDetailId; }
			set
			{
				if (Equals(value, _OrderDetailId)) return;
				_OrderDetailId = value;
				NotifyPropertyChanged(() => OrderDetailId);
			}
		}
		private int _OrderDetailId;

		public int OrderId
		{ 
			get { return _OrderId; }
			set
			{
				if (Equals(value, _OrderId)) return;
				_OrderId = value;
				NotifyPropertyChanged(() => OrderId);
			}
		}
		private int _OrderId;

		public int ProductId
		{ 
			get { return _ProductId; }
			set
			{
				if (Equals(value, _ProductId)) return;
				_ProductId = value;
				NotifyPropertyChanged(() => ProductId);
			}
		}
		private int _ProductId;

		public decimal UnitPrice
		{ 
			get { return _UnitPrice; }
			set
			{
				if (Equals(value, _UnitPrice)) return;
				_UnitPrice = value;
				NotifyPropertyChanged(() => UnitPrice);
			}
		}
		private decimal _UnitPrice;

		public short Quantity
		{ 
			get { return _Quantity; }
			set
			{
				if (Equals(value, _Quantity)) return;
				_Quantity = value;
				NotifyPropertyChanged(() => Quantity);
			}
		}
		private short _Quantity;

		public float Discount
		{ 
			get { return _Discount; }
			set
			{
				if (Equals(value, _Discount)) return;
				_Discount = value;
				NotifyPropertyChanged(() => Discount);
			}
		}
		private float _Discount;

		public Order Order
		{
			get { return _Order; }
			set
			{
				if (Equals(value, _Order)) return;
				_Order = value;
				OrderChangeTracker = _Order == null ? null
					: new ChangeTrackingCollection<Order> { _Order };
				NotifyPropertyChanged(() => Order);
			}
		}
		private Order _Order;
		private ChangeTrackingCollection<Order> OrderChangeTracker { get; set; }

		public Product Product
		{
			get { return _Product; }
			set
			{
				if (Equals(value, _Product)) return;
				_Product = value;
				ProductChangeTracker = _Product == null ? null
					: new ChangeTrackingCollection<Product> { _Product };
				NotifyPropertyChanged(() => Product);
			}
		}
		private Product _Product;
		private ChangeTrackingCollection<Product> ProductChangeTracker { get; set; }

	}
}


<|start_filename|>Source/Tests/TrackableEntities.EF.5.Tests/Helpers/TrackingStateHelper.cs<|end_filename|>
﻿using System;
using System.Collections;
using System.Collections.Generic;
using TrackableEntities.Common;

namespace TrackableEntities.EF.Tests
{
    internal static class TrackingStateHelper
    {
        // Recursively set tracking state
        public static void SetTrackingState(this ITrackable item,
            TrackingState state, ObjectVisitationHelper visitationHelper = null)
        {
            // Prevent endless recursion
            ObjectVisitationHelper.EnsureCreated(ref visitationHelper);
            if (!visitationHelper.TryVisit(item)) return;

            foreach (var navProp in item.GetNavigationProperties())
            {
                foreach (var refProp in navProp.AsReferenceProperty())
                {
                    refProp.EntityReference.SetTrackingState(state, visitationHelper);
                    refProp.EntityReference.TrackingState = state;
                }

                foreach (var colProp in navProp.AsCollectionProperty())
                {
                    foreach (ITrackable child in colProp.EntityCollection)
                    {
                        child.SetTrackingState(state, visitationHelper);
                        child.TrackingState = state;
                    }
                }
            }
        }

        // Recursively get tracking states
        public static IEnumerable<TrackingState> GetTrackingStates
            (this ITrackable item, TrackingState? trackingState = null,
            ObjectVisitationHelper visitationHelper = null)
        {
            // Prevent endless recursion
            ObjectVisitationHelper.EnsureCreated(ref visitationHelper);
            if (!visitationHelper.TryVisit(item)) yield break;

            foreach (var navProp in item.GetNavigationProperties())
            {
                foreach (var refProp in navProp.AsReferenceProperty())
                {
                    foreach (var state in refProp.EntityReference.GetTrackingStates(visitationHelper: visitationHelper))
                    {
                        if (trackingState == null || state == trackingState)
                            yield return state;
                    }
                }

                foreach (var colProp in navProp.AsCollectionProperty())
                {
                    foreach (ITrackable child in colProp.EntityCollection)
                    {
                        foreach (var state in child.GetTrackingStates(visitationHelper: visitationHelper))
                        {
                            if (trackingState == null || state == trackingState)
                                yield return state;
                        }
                    }
                }
            }
            yield return item.TrackingState;
        }

        // Recursively get modified properties
        public static IEnumerable<IEnumerable<string>> GetModifiedProperties
            (this ITrackable item, ObjectVisitationHelper visitationHelper = null)
        {
            // Prevent endless recursion
            ObjectVisitationHelper.EnsureCreated(ref visitationHelper);
            if (!visitationHelper.TryVisit(item)) yield break;

            foreach (var navProp in item.GetNavigationProperties())
            {
                foreach (var refProp in navProp.AsReferenceProperty())
                {
                    foreach (var modifiedProps in refProp.EntityReference.GetModifiedProperties(visitationHelper))
                    {
                        yield return modifiedProps;
                    }
                }

                foreach (var colProp in navProp.AsCollectionProperty())
                {
                    foreach (ITrackable child in colProp.EntityCollection)
                    {
                        foreach (var modifiedProps in child.GetModifiedProperties(visitationHelper))
                        {
                            yield return modifiedProps;
                        }
                    }
                }
            }
            yield return item.ModifiedProperties;
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Inheritance/SampleWebApi.Inheritance.WebApi/Controllers/CategoryController.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using TrackableEntities;
using TrackableEntities.Common;
using TrackableEntities.EF6;
using SampleWebApi.Inheritance.Shared.Entities.Contexts;
using SampleWebApi.Inheritance.Shared.Entities.Models;

namespace SampleWebApi.Inheritance.WebApi.Controllers
{
    public class CategoryController : ApiController
    {
        private readonly NorthwindSlimInheritance _dbContext = new NorthwindSlimInheritance();

        // GET api/Category
        [ResponseType(typeof(IEnumerable<Category>))]
        public async Task<IHttpActionResult> GetCategories()
        {
            IEnumerable<Category> entities = await _dbContext.Categories
                .ToListAsync();

            return Ok(entities);
        }

        // GET api/Category/5
        [ResponseType(typeof(Category))]
        public async Task<IHttpActionResult> GetCategory(int id)
        {
            Category entity = await _dbContext.Categories
                .SingleOrDefaultAsync(e => e.CategoryId == id);

            if (entity == null)
            {
                return NotFound();
            }

            return Ok(entity);
        }

        // POST api/Category
        [ResponseType(typeof(Category))]
        public async Task<IHttpActionResult> PostCategory(Category entity)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            entity.TrackingState = TrackingState.Added;
            _dbContext.ApplyChanges(entity);


            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateException)
            {
                if (_dbContext.Categories.Any(e => e.CategoryId == entity.CategoryId))
                {
                    return Conflict();
                }
                throw;
            }

            await _dbContext.LoadRelatedEntitiesAsync(entity);
            entity.AcceptChanges();
            return CreatedAtRoute("DefaultApi", new { id = entity.CategoryId }, entity);
        }

        // PUT api/Category
        [ResponseType(typeof(Category))]
        public async Task<IHttpActionResult> PutCategory(Category entity)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            _dbContext.ApplyChanges(entity);

            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!_dbContext.Categories.Any(e => e.CategoryId == entity.CategoryId))
                {
                    return Conflict();
                }
                throw;
            }

            await _dbContext.LoadRelatedEntitiesAsync(entity);
            entity.AcceptChanges();
            return Ok(entity);
        }

        // DELETE api/Category/5
        public async Task<IHttpActionResult> DeleteCategory(int id)
        {
            Category entity = await _dbContext.Categories
                .SingleOrDefaultAsync(e => e.CategoryId == id);
            if (entity == null)
            {
                return Ok();
            }

            entity.TrackingState = TrackingState.Deleted;
            _dbContext.ApplyChanges(entity);

            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!_dbContext.Categories.Any(e => e.CategoryId == entity.CategoryId))
                {
                    return Conflict();
                }
                throw;
            }

            return Ok();
        }

        protected override void Dispose(bool disposing)
        {
            _dbContext.Dispose();
            base.Dispose(disposing);
        }
    }
}


<|start_filename|>Extensions/Common/Wizards/TrackableEntities.TemplateWizard/RootWizard.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.IO;
using System.Reflection;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.TemplateWizard;

namespace TrackableEntities.TemplateWizard
{
    // Root wizard is used by root project vstemplate
    public class RootWizard : IWizard
    {
        // Use to communicate $saferootprojectname$ to ChildWizard
        public static Dictionary<string, string> RootDictionary =
            new Dictionary<string, string>();

        // Fields
        private DTE2 _dte2;
        private string _templateName;

        // Add global replacement parameters
        public void RunStarted(object automationObject, 
            Dictionary<string, string> replacementsDictionary, 
            WizardRunKind runKind, object[] customParams)
        {
            // Get template name
            _templateName = Path.GetFileNameWithoutExtension((string)customParams[0]);

            // Select entities template
            EntitiesWizard.SelectEntitiesTemplate(true, _templateName);

            // Place $parentwizardname$ in root dictionary
            RootDictionary[Constants.DictionaryEntries.ParentWizardName] = 
                Constants.ParentWizards.RootWizard;

            // Place "$saferootprojectname$ in the global dictionary.
            RootDictionary[Constants.DictionaryEntries.SafeRootProjectName] = 
                replacementsDictionary[Constants.DictionaryEntries.SafeProjectName];

            // Get DTE
            _dte2 = (DTE2)automationObject;
        }

        public void BeforeOpeningFile(ProjectItem projectItem)
        {
        }

        public void ProjectFinishedGenerating(Project project)
        {
        }

        public void ProjectItemFinishedGenerating(ProjectItem projectItem)
        {
        }

        public void RunFinished()
        {
            // Add ReadMe file to solution folder
            var solution = (Solution2)_dte2.Solution;
            solution.AddSolutionFolder("Solution Items");

            // Copy readme file to solution directory and add to solution folder
            string sourceReadMePath = GetTemplateReadMePath(_templateName);
            string destReadMePath = GetDestReadMePath(solution, _templateName);
            File.Copy(sourceReadMePath, destReadMePath);
            if (File.Exists(destReadMePath))
                _dte2.ItemOperations.AddExistingItem(destReadMePath);

            // Set startup project
            string extension = null;
            if (_templateName == Constants.ProjectTemplates.TrackableWcfService)
                extension = ".Service.Web";
            else if (_templateName == Constants.ProjectTemplates.TrackableWebApi ||
                _templateName == Constants.ProjectTemplates.TrackableWebApiPatterns)
                extension = ".WebApi";
            if (extension != null)
            {
                Project startupProject = GetProject(extension);
                if (startupProject != null)
                {
                    _dte2.Solution.SolutionBuild.StartupProjects = startupProject.UniqueName;
                } 
            }
        }

        public bool ShouldAddProjectItem(string filePath)
        {
            return true;
        }

        private Project GetProject(string extension)
        {
            string projectName = RootDictionary[Constants.DictionaryEntries.SafeRootProjectName] + extension;
            foreach (Project project in _dte2.Solution.Projects)
            {
                if (Path.GetFileNameWithoutExtension(project.FullName).Equals(projectName))
                {
                    return project;
                }
            }
            return null;
        }

        private string GetDestReadMePath(Solution2 solution, string templateName)
        {
            var solutionPath = solution.Properties.Item("Path").Value as string;
            if (string.IsNullOrWhiteSpace(solutionPath)) return null;
            string solutionDir = new FileInfo(solutionPath).DirectoryName;
            if (string.IsNullOrWhiteSpace(solutionDir)) return null;
            string readMeFileName = GetReadMeFileName(templateName);
            return Path.Combine(solutionDir, readMeFileName);
        }

        private string GetReadMeFileName(string templateName)
        {
            switch (templateName)
            {
                case Constants.ProjectTemplates.TrackableWcfService:
                    return Constants.ReadMeFiles.TrackableWcf;
                case Constants.ProjectTemplates.TrackableWebApi:
                    return Constants.ReadMeFiles.TrackableWebApi;
                case Constants.ProjectTemplates.TrackableWebApiPatterns:
                    return Constants.ReadMeFiles.WebApiPatternsSample;
                default:
                    return null;
            }
        }

        private string GetTemplateReadMePath(string templateName)
        {
            string readMeFileName = GetReadMeFileName(templateName);
            if (readMeFileName == null) return null;
            string templateReadMePath = GetTemplateFilePath(readMeFileName);
            return templateReadMePath;
        }

        private string GetTemplateFilePath(string fileName)
        {
            string dirPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            return Path.Combine(dirPath, fileName);
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample/WebApiSample.Shared.Entities.Data/Contexts/NorthwindSlim.cs<|end_filename|>
using System.Data.Entity;
using WebApiSample.Shared.Entities.Data.Models.Mapping;
using WebApiSample.Shared.Entities.Portable.Models;

namespace WebApiSample.Shared.Entities.Data.Contexts
{
    public partial class NorthwindSlim : DbContext
    {
        static NorthwindSlim()
        {
            Database.SetInitializer<NorthwindSlim>(null);
        }

        public NorthwindSlim()
            : base("Name=NorthwindSlimContext")
        {
            this.Configuration.ProxyCreationEnabled = false;
        }

        public virtual DbSet<Category> Categories { get; set; }
        public virtual DbSet<Customer> Customers { get; set; }
        public virtual DbSet<CustomerSetting> CustomerSettings { get; set; }
        public virtual DbSet<Employee> Employees { get; set; }
        public virtual DbSet<Order> Orders { get; set; }
        public virtual DbSet<OrderDetail> OrderDetails { get; set; }
        public virtual DbSet<Product> Products { get; set; }
        public virtual DbSet<Territory> Territories { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new CategoryMap());
            modelBuilder.Configurations.Add(new CustomerMap());
            modelBuilder.Configurations.Add(new CustomerSettingMap());
            modelBuilder.Configurations.Add(new EmployeeMap());
            modelBuilder.Configurations.Add(new OrderMap());
            modelBuilder.Configurations.Add(new OrderDetailMap());
            modelBuilder.Configurations.Add(new ProductMap());
            modelBuilder.Configurations.Add(new TerritoryMap());
        }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Patterns/WebApiSample.Service.EF/Contexts/INorthwindSlimContext.cs<|end_filename|>
using System;
using System.Data.Entity;
using WebApiSample.Service.Entities.Models;

namespace WebApiSample.Service.EF.Contexts
{
    public interface INorthwindSlimContext
    {
        IDbSet<Category> Categories { get; set; }
        IDbSet<Customer> Customers { get; set; }
        IDbSet<CustomerSetting> CustomerSettings { get; set; }
        IDbSet<Order> Orders { get; set; }
        IDbSet<OrderDetail> OrderDetails { get; set; }
        IDbSet<Product> Products { get; set; }
        IDbSet<Employee> Employees { get; set; }
        IDbSet<Territory> Territories { get; set; }
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/ModelExtensions/CustomerSetting.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Newtonsoft.Json;

namespace TrackableEntities.EF.Tests.NorthwindModels
{
    [JsonObject(IsReference = true)]
    public partial class CustomerSetting : ITrackable
    {
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/Features/UpdateOrder.feature.cs<|end_filename|>
﻿// ------------------------------------------------------------------------------
//  <auto-generated>
//      This code was generated by SpecFlow (http://www.specflow.org/).
//      SpecFlow Version:1.9.0.77
//      SpecFlow Generator Version:1.9.0.0
//      Runtime Version:4.0.30319.34209
// 
//      Changes to this file may cause incorrect behavior and will be lost if
//      the code is regenerated.
//  </auto-generated>
// ------------------------------------------------------------------------------
#region Designer generated code
#pragma warning disable
namespace TrackableEntities.Tests.Acceptance.Features
{
    using TechTalk.SpecFlow;
    
    
    [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.9.0.77")]
    [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    public partial class UpdateOrderFeature : Xunit.IUseFixture<UpdateOrderFeature.FixtureData>, System.IDisposable
    {
        
        private static TechTalk.SpecFlow.ITestRunner testRunner;
        
#line 1 "UpdateOrder.feature"
#line hidden
        
        public UpdateOrderFeature()
        {
            this.TestInitialize();
        }
        
        public static void FeatureSetup()
        {
            testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner();
            TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Update Order", "In order to update orders\r\nAs a Web API client\r\nI want to save orders to the data" +
                    "base", ProgrammingLanguage.CSharp, ((string[])(null)));
            testRunner.OnFeatureStart(featureInfo);
        }
        
        public static void FeatureTearDown()
        {
            testRunner.OnFeatureEnd();
            testRunner = null;
        }
        
        public virtual void TestInitialize()
        {
        }
        
        public virtual void ScenarioTearDown()
        {
            testRunner.OnScenarioEnd();
        }
        
        public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo)
        {
            testRunner.OnScenarioStart(scenarioInfo);
        }
        
        public virtual void ScenarioCleanup()
        {
            testRunner.CollectScenarioErrors();
        }
        
        public virtual void SetFixture(UpdateOrderFeature.FixtureData fixtureData)
        {
        }
        
        void System.IDisposable.Dispose()
        {
            this.ScenarioTearDown();
        }
        
        [Xunit.FactAttribute()]
        [Xunit.TraitAttribute("FeatureTitle", "Update Order")]
        [Xunit.TraitAttribute("Description", "Create Order")]
        public virtual void CreateOrder()
        {
            TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Create Order", new string[] {
                        "update_orders"});
#line 7
this.ScenarioSetup(scenarioInfo);
#line hidden
            TechTalk.SpecFlow.Table table1 = new TechTalk.SpecFlow.Table(new string[] {
                        "CustomerId"});
            table1.AddRow(new string[] {
                        "ABCD"});
#line 8
 testRunner.Given("the following new customer orders", ((string)(null)), table1, "Given ");
#line 11
 testRunner.When("I submit a POST to create an order", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line 12
 testRunner.Then("the request should return the new order", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
            this.ScenarioCleanup();
        }
        
        [Xunit.FactAttribute()]
        [Xunit.TraitAttribute("FeatureTitle", "Update Order")]
        [Xunit.TraitAttribute("Description", "Modify Order")]
        public virtual void ModifyOrder()
        {
            TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Modify Order", new string[] {
                        "update_orders"});
#line 15
this.ScenarioSetup(scenarioInfo);
#line hidden
            TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] {
                        "CustomerId"});
            table2.AddRow(new string[] {
                        "ABCD"});
#line 16
 testRunner.Given("the following existing customer orders", ((string)(null)), table2, "Given ");
#line 19
 testRunner.And("the order is modified", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
#line 20
 testRunner.When("I submit a PUT to modify an order", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line 21
 testRunner.Then("the request should return the modified order", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
            this.ScenarioCleanup();
        }
        
        [Xunit.FactAttribute()]
        [Xunit.TraitAttribute("FeatureTitle", "Update Order")]
        [Xunit.TraitAttribute("Description", "Add Order Details")]
        public virtual void AddOrderDetails()
        {
            TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Add Order Details", new string[] {
                        "update_orders"});
#line 24
this.ScenarioSetup(scenarioInfo);
#line hidden
            TechTalk.SpecFlow.Table table3 = new TechTalk.SpecFlow.Table(new string[] {
                        "CustomerId"});
            table3.AddRow(new string[] {
                        "ABCD"});
#line 25
 testRunner.Given("the following existing customer orders", ((string)(null)), table3, "Given ");
#line 28
 testRunner.And("order details are added", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
#line 29
 testRunner.When("I submit a PUT to modify an order", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line 30
 testRunner.Then("the request should return the added order details", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
            this.ScenarioCleanup();
        }
        
        [Xunit.FactAttribute()]
        [Xunit.TraitAttribute("FeatureTitle", "Update Order")]
        [Xunit.TraitAttribute("Description", "Delete Order")]
        public virtual void DeleteOrder()
        {
            TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Delete Order", new string[] {
                        "update_orders"});
#line 33
this.ScenarioSetup(scenarioInfo);
#line hidden
            TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] {
                        "CustomerId"});
            table4.AddRow(new string[] {
                        "ABCD"});
#line 34
 testRunner.Given("the following existing customer orders", ((string)(null)), table4, "Given ");
#line 37
 testRunner.When("I submit a DELETE to delete an order", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line 38
 testRunner.Then("the order should be deleted", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
            this.ScenarioCleanup();
        }
        
        [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.9.0.77")]
        [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
        public class FixtureData : System.IDisposable
        {
            
            public FixtureData()
            {
                UpdateOrderFeature.FeatureSetup();
            }
            
            void System.IDisposable.Dispose()
            {
                UpdateOrderFeature.FeatureTearDown();
            }
        }
    }
}
#pragma warning restore
#endregion


<|start_filename|>Source/Tests/TrackableEntities.EF.5.Tests/NorthwindModels/Product.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TrackableEntities.EF.Tests.NorthwindModels
{
    public partial class Product : ITrackable
    {
        [Key]
        public int ProductId { get; set; }
        public string ProductName { get; set; }
        public decimal UnitPrice { get; set; }
        public bool Discontinued { get; set; }

        public int CategoryId { get; set; }
        [ForeignKey("CategoryId")]
        public Category Category { get; set; }

        public int? PromoId { get; set; }
        [ForeignKey("PromoId")]
        public HolidayPromo HolidayPromo { get; set; }

        [ForeignKey("ProductInfo"), Column(Order = 1)]
        public int? ProductInfoKey1 { get; set; }
        [ForeignKey("ProductInfo"), Column(Order = 2)]
        public int? ProductInfoKey2 { get; set; }
        public ProductInfo ProductInfo { get; set; }

        [NotMapped]
        public TrackingState TrackingState { get; set; }
        [NotMapped]
        public ICollection<string> ModifiedProperties { get; set; }
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.Relations/WebApiSample.WebApi/Controllers/TerritoryController.cs<|end_filename|>
﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using TrackableEntities;
using TrackableEntities.EF6;
using TrackableEntities.Common;
using WebApiSample.Service.Entities.Models;
using WebApiSample.Service.Entities.Contexts;

namespace WebApiSample.Service.WebApi.Controllers
{
    public class TerritoryController : ApiController
    {
        private readonly NorthwindSlimContext _dbContext = new NorthwindSlimContext();

        // GET api/Territory
        [ResponseType(typeof(IEnumerable<Territory>))]
        public async Task<IHttpActionResult> GetTerritories()
        {
	        IEnumerable<Territory> territories = await _dbContext.Territories.ToListAsync();
	
            return Ok(territories);
        }

        // GET api/Territory/5
        [ResponseType(typeof(Territory))]
        public async Task<IHttpActionResult> GetTerritory(string id)
        {
	        Territory territory = await _dbContext.Territories.SingleOrDefaultAsync(t => t.TerritoryId == id);
	
            if (territory == null)
            {
                return NotFound();
            }

            return Ok(territory);
        }

        // POST api/Territory
        [ResponseType(typeof(Territory))]
        public async Task<IHttpActionResult> PostTerritory(Territory territory)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            territory.TrackingState = TrackingState.Added;
            _dbContext.ApplyChanges(territory);


            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateException)
            {
                if (_dbContext.Territories.Any(t => t.TerritoryId == territory.TerritoryId))
                {
                    return Conflict();
                }
                throw;
            }

            await _dbContext.LoadRelatedEntitiesAsync(territory);
            territory.AcceptChanges();
            return CreatedAtRoute("DefaultApi", new { id = territory.TerritoryId }, territory);
        }

        // PUT api/Territory
        [ResponseType(typeof(Territory))]
        public async Task<IHttpActionResult> PutTerritory(Territory territory)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            _dbContext.ApplyChanges(territory);

            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!_dbContext.Territories.Any(t => t.TerritoryId == territory.TerritoryId))
                {
                    return Conflict();
                }
                throw;
            }

			await _dbContext.LoadRelatedEntitiesAsync(territory);
			territory.AcceptChanges();
	        return Ok(territory);
        }

        // DELETE api/Territory/5
        public async Task<IHttpActionResult> DeleteTerritory(string id)
        {
			Territory territory = await _dbContext.Territories
				.SingleOrDefaultAsync(t => t.TerritoryId == id);
			if (territory == null)
            {
                return Ok();
            }

			territory.TrackingState = TrackingState.Deleted;
			_dbContext.ApplyChanges(territory);

            try
            {
	            await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!_dbContext.Territories.Any(t => t.TerritoryId == territory.TerritoryId))
                {
                    return Conflict();
                }
                throw;
            }

            return Ok();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _dbContext.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}

<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/WebHost/WebHostClient.cs<|end_filename|>
﻿using System;
using System.Net.Http;

namespace TrackableEntities.Tests.Acceptance.WebHost
{
    public class WebHostClient
    {
        private WebHostClient() { }

        public static HttpClient Create(int portNumber)
        {
            string baseAddress = string.Format("http://{0}:{1}/",
                Constants.WebHost.HostName, portNumber);
            var client = new HttpClient { BaseAddress = new Uri(baseAddress) };
            return client;
        }
    }
}


<|start_filename|>Extensions/VS2015/Output/Extract/ItemTemplates/WebApiController/WebApiController.cs<|end_filename|>
﻿using System;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Web.Http;
using System.Web.Http.Description;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using TrackableEntities;
using TrackableEntities.EF6;
using TrackableEntities.Common;
using $entitiesNamespace$;

// NOTE: Primary key name and/or type may need to be set manually.

namespace $rootnamespace$
{
	public class $safeitemname$ : ApiController
	{
        private readonly $dbContextName$ _dbContext = new $dbContextName$();

        // GET api/$entityName$
        [ResponseType(typeof(IEnumerable<$entityName$>))]
        public async Task<IHttpActionResult> Get$entitySetName$()
        {
	        IEnumerable<$entityName$> entities = await _dbContext.$entitySetName$
			    // TODO: Add Includes for reference and/or collection properties
				.ToListAsync();
	
            return Ok(entities);
        }

        // GET api/$entityName$/5
        [ResponseType(typeof($entityName$))]
        public async Task<IHttpActionResult> Get$entityName$(int id)
        {
	        $entityName$ entity = await _dbContext.$entitySetName$
			    // TODO: Add Includes for reference and/or collection properties
				.SingleOrDefaultAsync(e => e.$entityName$Id == id);
	
            if (entity == null)
            {
                return NotFound();
            }

            return Ok(entity);
        }

        // POST api/$entityName$
        [ResponseType(typeof($entityName$))]
        public async Task<IHttpActionResult> Post$entityName$($entityName$ entity)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            entity.TrackingState = TrackingState.Added;
            _dbContext.ApplyChanges(entity);


            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateException)
            {
                if (_dbContext.$entitySetName$.Any(e => e.$entityName$Id == entity.$entityName$Id))
                {
                    return Conflict();
                }
                throw;
            }

            await _dbContext.LoadRelatedEntitiesAsync(entity);
            entity.AcceptChanges();
            return CreatedAtRoute("DefaultApi", new { id = entity.$entityName$Id }, entity);
        }

        // PUT api/$entityName$
        [ResponseType(typeof($entityName$))]
        public async Task<IHttpActionResult> Put$entityName$($entityName$ entity)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            _dbContext.ApplyChanges(entity);

            try
            {
                await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!_dbContext.$entitySetName$.Any(e => e.$entityName$Id == entity.$entityName$Id))
                {
                    return Conflict();
                }
                throw;
            }

			await _dbContext.LoadRelatedEntitiesAsync(entity);
			entity.AcceptChanges();
	        return Ok(entity);
        }

        // DELETE api/$entityName$/5
        public async Task<IHttpActionResult> Delete$entityName$(int id)
        {
			$entityName$ entity = await _dbContext.$entitySetName$
			    // TODO: Include child entities if any
				.SingleOrDefaultAsync(e => e.$entityName$Id == id);
			if (entity == null)
            {
                return Ok();
            }

			entity.TrackingState = TrackingState.Deleted;
			_dbContext.ApplyChanges(entity);

            try
            {
	            await _dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!_dbContext.$entitySetName$.Any(e => e.$entityName$Id == entity.$entityName$Id))
                {
                    return Conflict();
                }
                throw;
            }

            return Ok();
        }

        protected override void Dispose(bool disposing)
        {
            _dbContext.Dispose();
            base.Dispose(disposing);
        }
    }
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/IUseFixture_WORKAROUND.cs<|end_filename|>
﻿namespace Xunit
{
    /// <summary>
    /// XUnit backwards compatibility for feature generator
    /// </summary>
    /// <remarks>
    /// Delete this when generator no longer uses this class - 5/25/15
    /// </remarks>
    /// <typeparam name="T"></typeparam>
    public interface IUseFixture<T> : Xunit.IClassFixture<T> where T : class, new()
    {
    }
}

<|start_filename|>Source/Tests/TrackableEntities.EF.5.Tests/DbContextTests.cs<|end_filename|>
﻿using System;
using System.Data.Entity;
using System.Linq;
using System.Collections.Generic;
using System.Data;
using TrackableEntities.EF.Tests;
using TrackableEntities.EF.Tests.NorthwindModels;
using Xunit;

#if EF_6
namespace TrackableEntities.EF6.Tests
#else
namespace TrackableEntities.EF5.Tests
#endif
{
    public class DbContextTests
    {
        // Recreate database if model changed.
        // Specify CreateDbOptions.DropCreateDatabaseSeed to seed with real data.
        const CreateDbOptions CreateNorthwindDbOptions = CreateDbOptions.DropCreateDatabaseIfModelChanges;

        #region Update Parent State

        [Fact]
        public void Adding_Parent_Should_Mark_Children_As_Added()
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var product = new Product { ProductId = 1, CategoryId = 1, ProductName = "TestProduct" };
            var category = new Category
            {
                CategoryId = 1,
                CategoryName = "TestCategory",
                Products = new List<Product> { product }
            };

            // Act
            context.Entry(category).State = EntityState.Added;

            // Assert
            Assert.Equal(EntityState.Added, context.Entry(product).State);
        }

        [Fact]
        public void Modifying_Parent_Should_Mark_Children_As_Unchanged()
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var product = new Product { ProductId = 1, CategoryId = 1, ProductName = "TestProduct" };
            var category = new Category
            {
                CategoryId = 1,
                CategoryName = "TestCategory",
                Products = new List<Product> { product }
            };

            // Act
            context.Entry(category).State = EntityState.Modified;

            // Assert
            Assert.Equal(EntityState.Unchanged, context.Entry(product).State);
        }

        [Fact]
        public void Deleting_Parent_And_Children_Should_Mark_Children_As_Deleted()
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var product = new Product { ProductId = 1, CategoryId = 1, ProductName = "TestProduct" };
            var category = new Category
            {
                CategoryId = 1,
                CategoryName = "TestCategory",
                Products = new List<Product> { product }
            };

            // Act
            context.Entry(product).State = EntityState.Unchanged;
            context.Entry(category).State = EntityState.Unchanged;
            context.Entry(product).State = EntityState.Deleted;
            context.Entry(category).State = EntityState.Deleted;

            // Assert
            Assert.Equal(EntityState.Deleted, context.Entry(product).State);
        }

        #endregion

        #region Update Parent State And Save

        [Fact]
        public void Adding_Parent_Should_Add_Children()
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var product = new Product { ProductName = "TestProduct" };
            var category = new Category
            {
                CategoryName = "TestCategory",
                Products = new List<Product> { product }
            };

            // Act
            context.Entry(category).State = EntityState.Added;
            context.SaveChanges();

            // Assert
            Assert.Equal(EntityState.Unchanged, context.Entry(product).State);
        }

        [Fact]
        public void Modifying_Parent_Should_Keep_Children_Unchanged()
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var product = new Product { ProductName = "TestProduct" };
            var category = new Category
            {
                CategoryName = "TestCategory",
                Products = new List<Product> { product }
            };
            context.Categories.Add(category);
            context.SaveChanges();
            int categoryId = category.CategoryId;
            int productId = product.ProductId;
            context.Entry(product).State = EntityState.Detached;
            context.Entry(category).State = EntityState.Detached;
            product = new Product { ProductId = productId, CategoryId = categoryId, ProductName = "TestProduct" };
            category = new Category
            {
                CategoryId = categoryId,
                CategoryName = "TestCategory_Changed",
                Products = new List<Product> { product }
            };

            // Act
            context.Entry(product).State = EntityState.Unchanged;
            context.Entry(category).State = EntityState.Modified;
            context.SaveChanges();

            // Assert
            Assert.Equal(EntityState.Unchanged, context.Entry(product).State);
        }

        [Fact]
        public void Deleting_Parent_Should_Delete_Children()
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var product = new Product { ProductName = "TestProduct"};
            var category = new Category
            {
                CategoryName = "TestCategory",
                Products = new List<Product> { product }
            };
            context.Categories.Add(category);
            context.SaveChanges();
            int categoryId = category.CategoryId;
            int productId = product.ProductId;
            context.Entry(product).State = EntityState.Detached;
            context.Entry(category).State = EntityState.Detached;
            product = new Product { ProductId = productId, CategoryId = categoryId, ProductName = "TestProduct" };
            category = new Category
            {
                CategoryId = categoryId,
                CategoryName = "TestCategory",
                Products = new List<Product> { product }
            };

            // Act
            // First mark child and parent as unchanged (to attach)
            context.Entry(product).State = EntityState.Unchanged;
            context.Entry(category).State = EntityState.Unchanged;

            // Then mark child and parent as deleted
            context.Entry(product).State = EntityState.Deleted;
            context.Entry(category).State = EntityState.Deleted;
            context.SaveChanges();

            // Assert
            Assert.Equal(EntityState.Detached, context.Entry(category).State);
            Assert.Equal(EntityState.Detached, context.Entry(product).State);
        }

        #endregion

        #region Update Child State

        [Fact]
        public void Adding_Child_To_Unchanged_Parent_Should_Keep_Parent_Unchanged()
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var product = new Product { ProductName = "TestProduct" };
            var category = new Category
            {
                CategoryName = "TestCategory",
                Products = new List<Product> { product }
            };

            // Act
            context.Entry(category).State = EntityState.Unchanged;
            context.Entry(product).State = EntityState.Added;

            // Assert
            Assert.Equal(EntityState.Unchanged, context.Entry(category).State);
        }

        [Fact]
        public void Adding_Child_To_Modified_Parent_Should_Keep_Parent_Modified()
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var product = new Product { ProductName = "TestProduct" };
            var category = new Category
            {
                CategoryName = "TestCategory",
                Products = new List<Product> { product }
            };

            // Act
            context.Entry(category).State = EntityState.Modified;
            context.Entry(product).State = EntityState.Added;

            // Assert
            Assert.Equal(EntityState.Modified, context.Entry(category).State);
        }

        [Fact]
        public void Modified_Child_From_Unchanged_Parent_Should_Keep_Parent_Unchanged()
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var product = new Product { ProductName = "TestProduct" };
            var category = new Category
            {
                CategoryName = "TestCategory",
                Products = new List<Product> { product }
            };

            // Act
            context.Entry(category).State = EntityState.Unchanged;
            context.Entry(product).State = EntityState.Modified;

            // Assert
            Assert.Equal(EntityState.Unchanged, context.Entry(category).State);
        }

        [Fact]
        public void Modified_Child_From_Modified_Parent_Should_Keep_Parent_Modified()
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var product = new Product { ProductName = "TestProduct" };
            var category = new Category
            {
                CategoryName = "TestCategory",
                Products = new List<Product> { product }
            };

            // Act
            context.Entry(category).State = EntityState.Modified;
            context.Entry(product).State = EntityState.Modified;

            // Assert
            Assert.Equal(EntityState.Modified, context.Entry(category).State);
        }

        [Fact]
        public void Deleting_Child_From_Unchanged_Parent_Should_Keep_Parent_Unchanged()
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var product = new Product { ProductName = "TestProduct" };
            var category = new Category
            {
                CategoryName = "TestCategory",
                Products = new List<Product> { product }
            };

            // Act
            context.Entry(category).State = EntityState.Unchanged;
            context.Entry(product).State = EntityState.Deleted;

            // Assert
            Assert.Equal(EntityState.Unchanged, context.Entry(category).State);
        }

        [Fact]
        public void Deleting_Child_From_Modified_Parent_Should_Keep_Parent_Modified()
        {
            // Arrange
            var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
            var product = new Product { ProductName = "TestProduct" };
            var category = new Category
            {
                CategoryName = "TestCategory",
                Products = new List<Product> { product }
            };

            // Act
            context.Entry(category).State = EntityState.Modified;
            context.Entry(product).State = EntityState.Deleted;

            // Assert
            Assert.Equal(EntityState.Modified, context.Entry(category).State);
        }

        #endregion
    }
}


<|start_filename|>Samples/VS2013/WebApiSample.ModelFirst/WebApiSample.Service.Entities/CustomerSetting.cs<|end_filename|>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace WebApiSample.Service.Entities
{
    using System;
    using System.Collections.Generic;
    using TrackableEntities;
    
    public partial class CustomerSetting : ITrackable, IMergeable
    {
        public string CustomerId { get; set; }
        public string Setting { get; set; }
    
        public Customer Customer { get; set; }
    
        public TrackingState TrackingState { get; set; }
        public ICollection<string> ModifiedProperties { get; set; }
        public Guid EntityIdentifier { get; set; }
    }
}


<|start_filename|>Samples/VS2012/WcfSample/WcfSample.Client.Entities/Models/OrderDetail.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using TrackableEntities;
using TrackableEntities.Client;

namespace WcfSample.Client.Entities.Models
{
    [JsonObject(IsReference = true)]
    [DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
    public partial class OrderDetail : ModelBase<OrderDetail>, IEquatable<OrderDetail>, ITrackable
    {
		[DataMember]
		public int OrderDetailId
		{ 
			get { return _OrderDetailId; }
			set
			{
				if (Equals(value, _OrderDetailId)) return;
				_OrderDetailId = value;
				NotifyPropertyChanged(m => m.OrderDetailId);
			}
		}
		private int _OrderDetailId;

		[DataMember]
		public int OrderId
		{ 
			get { return _OrderId; }
			set
			{
				if (Equals(value, _OrderId)) return;
				_OrderId = value;
				NotifyPropertyChanged(m => m.OrderId);
			}
		}
		private int _OrderId;

		[DataMember]
		public int ProductId
		{ 
			get { return _ProductId; }
			set
			{
				if (Equals(value, _ProductId)) return;
				_ProductId = value;
				NotifyPropertyChanged(m => m.ProductId);
			}
		}
		private int _ProductId;

		[DataMember]
		public decimal UnitPrice
		{ 
			get { return _UnitPrice; }
			set
			{
				if (Equals(value, _UnitPrice)) return;
				_UnitPrice = value;
				NotifyPropertyChanged(m => m.UnitPrice);
			}
		}
		private decimal _UnitPrice;

		[DataMember]
		public short Quantity
		{ 
			get { return _Quantity; }
			set
			{
				if (Equals(value, _Quantity)) return;
				_Quantity = value;
				NotifyPropertyChanged(m => m.Quantity);
			}
		}
		private short _Quantity;

		[DataMember]
		public float Discount
		{ 
			get { return _Discount; }
			set
			{
				if (Equals(value, _Discount)) return;
				_Discount = value;
				NotifyPropertyChanged(m => m.Discount);
			}
		}
		private float _Discount;

		[DataMember]
		public Order Order
		{
			get { return _Order; }
			set
			{
				if (Equals(value, _Order)) return;
				_Order = value;
				OrderChangeTracker = _Order == null ? null
					: new ChangeTrackingCollection<Order> { _Order };
				NotifyPropertyChanged(m => m.Order);
			}
		}
		private Order _Order;
		private ChangeTrackingCollection<Order> OrderChangeTracker { get; set; }

		[DataMember]
		public Product Product
		{
			get { return _Product; }
			set
			{
				if (Equals(value, _Product)) return;
				_Product = value;
				ProductChangeTracker = _Product == null ? null
					: new ChangeTrackingCollection<Product> { _Product };
				NotifyPropertyChanged(m => m.Product);
			}
		}
		private Product _Product;
		private ChangeTrackingCollection<Product> ProductChangeTracker { get; set; }

        #region Change Tracking

		[DataMember]
		public TrackingState TrackingState { get; set; }

		[DataMember]
		public ICollection<string> ModifiedProperties { get; set; }

		[JsonProperty, DataMember]
		private Guid EntityIdentifier { get; set; }

		#pragma warning disable 414

		[JsonProperty, DataMember]
		private Guid _entityIdentity = default(Guid);

		#pragma warning restore 414

		bool IEquatable<OrderDetail>.Equals(OrderDetail other)
		{
			if (EntityIdentifier != default(Guid))
				return EntityIdentifier == other.EntityIdentifier;
			return false;
		}
        #endregion
	}
}


<|start_filename|>Source/Tests.Acceptance/TrackableEntities.Tests.Acceptance/Helpers/HttpClientExtensions.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Net.Http;

namespace TrackableEntities.Tests.Acceptance.Helpers
{
    internal static class HttpClientExtensions
    {
        public static TEntity GetEntity<TEntity, TKey>(this HttpClient client, TKey id)
        {
            string request = string.Format("api/{0}/{1}", typeof(TEntity).Name, id);
            var response = client.GetAsync(request).Result;
            response.EnsureSuccessStatusCode();
            var result = response.Content.ReadAsAsync<TEntity>().Result;
            return result;
        }

        public static IEnumerable<TEntity> GetEntities<TEntity>(this HttpClient client)
        {
            string request = string.Format("api/{0}", typeof(TEntity).Name);
            var response = client.GetAsync(request).Result;
            response.EnsureSuccessStatusCode();
            var result = response.Content.ReadAsAsync<IEnumerable<TEntity>>().Result;
            return result;
        }

        public static TEntity CreateEntity<TEntity>(this HttpClient client, TEntity entity)
        {
            string request = string.Format("api/{0}", typeof(TEntity).Name);
            var response = client.PostAsJsonAsync(request, entity).Result;
            response.EnsureSuccessStatusCode();
            var result = response.Content.ReadAsAsync<TEntity>().Result;
            return result;
        }

        public static TEntity UpdateTEntity<TEntity>(this HttpClient client, TEntity entity)
        {
            string request = string.Format("api/{0}", typeof(TEntity).Name);
            var response = client.PutAsJsonAsync(request, entity).Result;
            response.EnsureSuccessStatusCode();
            var result = response.Content.ReadAsAsync<TEntity>().Result;
            return result;
        }

        public static void DeleteTEntity<TEntity, TKey>(this HttpClient client, TKey id)
        {
            string request = string.Format("api/{0}/{1}", typeof(TEntity).Name, id);
            var response = client.DeleteAsync(request);
            response.Result.EnsureSuccessStatusCode();
        }

        public static bool VerifyEntityDeleted<TEntity, TKey>(this HttpClient client, TKey id)
        {
            string request = string.Format("api/{0}/{1}", typeof(TEntity).Name, id);
            var response = client.GetAsync(request).Result;
            if (response.IsSuccessStatusCode) return false;
            return true;
        }
    }
}


<|start_filename|>Extensions/VS2015/Output/Extract/ItemTemplates/IEntityRepository/IEntityRepository.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using TrackableEntities.Patterns;
using $entitiesNamespace$;

namespace $rootnamespace$
{
    public interface $safeitemname$ : IRepository<$entityName$>, IRepositoryAsync<$entityName$>
    {
        Task<IEnumerable<$entityName$>> Get$entitySetName$();
        Task<$entityName$> Get$entityName$(int id);
        Task<bool> Delete$entityName$(int id);
    }
}


<|start_filename|>Extensions/Common/Wizards/EntitiesSelectionHarness/Program.cs<|end_filename|>
﻿using System;
using System.Windows.Forms;
using EntitiesSelectionWizard;

namespace EntitiesSelectionHarness
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            bool multiproject = MessageBox.Show(
                "Multi-Project?", "Project Type", MessageBoxButtons.YesNo) == DialogResult.Yes;
            bool webApiSharedPortable = false;
            if (multiproject)
            webApiSharedPortable = MessageBox.Show(
                "Web API Shared Portable?", "Shared Portable Exception", MessageBoxButtons.YesNo) == DialogResult.Yes;
            
            var result = DialogResult.OK;
            while (result != DialogResult.Cancel)
            {
                var dialog = new EntitiesSelectionDialog(multiproject, webApiSharedPortable);
                result = dialog.ShowDialog();
                if (result == DialogResult.Cancel) continue;
                string entitiesSelection = dialog.EntitiesSelection.ToString();
                MessageBox.Show(entitiesSelection, "Entities Selection");
            }
        }
    }
}


<|start_filename|>Extensions/VS2015/Output/Extract/ItemTemplates/IDatabaseContext/IDatabaseContext.cs<|end_filename|>
﻿using System;
using System.Data.Entity;

// TODO: Alter DbContext class to implement this interface and change
// each DbSet property to IDbSet

namespace $rootnamespace$
{
    public interface $safeitemname$
    {
        // TODO: Add IDbSet<Entity> properties for each entity set on the DbContext class
        //IDbSet<Entity> Entities { get; set; }
    }
}


<|start_filename|>Source/TrackableEntities.Patterns.EF.6/UnitOfWork.cs<|end_filename|>
﻿using System;
using System.Collections;
using System.Data.Entity;
using System.Threading;
using System.Threading.Tasks;

namespace TrackableEntities.Patterns.EF6
{
    /// <summary>
    /// General unit of work for committing changes across one or more repositories. 
    /// Inherit from this class to supply a specific DbContext. 
    /// Add a property for each respository for which unit of work must be done.
    /// </summary>
    public abstract class UnitOfWork : IUnitOfWork, IUnitOfWorkAsync, IDisposable
    {
        private bool _disposed;

        /// <summary>
        /// Constructs a new general unit of work.
        /// </summary>
        protected UnitOfWork() { }

        /// <summary>
        /// Constructs a new general unit of work.
        /// </summary>
        /// <param name="context">Entity Framework DbContext-derived class.</param>
        protected UnitOfWork(DbContext context)
        {
            Context = context;
        }

        /// <summary>
        /// Gets the DbContext for the unit of work.
        /// </summary>
        protected DbContext Context { get; set; }

        /// <summary>
        /// Disposes the DbContext.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Disposes the DbContext.
        /// </summary>
        /// <param name="disposing">True to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (_disposed) return;
            if (disposing) Context.Dispose();
            _disposed = true;
        }

        /// <summary>
        /// Saves changes made to one or more repositories.
        /// </summary>
        /// <returns>The number of objects saved.</returns>
        public virtual int SaveChanges()
        {
            if (_disposed)
                throw new ObjectDisposedException("UnitOfWork");
            return Context.SaveChanges();
        }

        /// <summary>
        /// Saves changes made to one or more repositories.
        /// </summary>
        /// <returns>A task that represents the asynchronous save operation. The task result contains the number of objects saved.</returns>
        public virtual async Task<int> SaveChangesAsync()
        {
            if (_disposed)
                throw new ObjectDisposedException("UnitOfWork");
            return await SaveChangesAsync(CancellationToken.None);
        }

        /// <summary>
        /// Saves changes made to one or more repositories.
        /// </summary>
        /// <param name="cancellationToken">A CancellationToken to observe while waiting for the task to complete.</param>
        /// <returns>A task that represents the asynchronous save operation. The task result contains the number of objects saved.</returns>
        public virtual async Task<int> SaveChangesAsync(CancellationToken cancellationToken)
        {
            if (_disposed)
                throw new ObjectDisposedException("UnitOfWork");
            return await Context.SaveChangesAsync(cancellationToken);
        }
    }
}


<|start_filename|>Samples/VS2012/WcfSample/WcfSample.Service.Core/IOrderService.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.ServiceModel;
using System.Threading.Tasks;
using WcfSample.Service.Entities.Models;

namespace WcfSample.Service.Core
{
    [ServiceContract(Namespace = "urn:trackable-entities:samples")]
    public interface IOrderService
    {
        [OperationContract]
        Task<IEnumerable<Order>> GetOrders();

        [OperationContract]
        Task<IEnumerable<Order>> GetCustomerOrders(string customerId);

        [OperationContract]
        Task<Order> GetOrder(int id);

        [OperationContract]
        Task<Order> UpdateOrder(Order order);

        [OperationContract]
        Task<Order> CreateOrder(Order order);

        [OperationContract]
        Task<bool> DeleteOrder(int id);
    }
}


<|start_filename|>Source/TrackableEntities.Patterns/IRepository.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;

namespace TrackableEntities.Patterns
{
    /// <summary>
    /// Generic repository interface with basic operations.
    /// </summary>
    /// <typeparam name="TEntity">Entity type</typeparam>
    public interface IRepository<TEntity>
        where TEntity : class
    {
        /// <summary>
        /// Finds an entity with the given primary key values. If no entity is found, then null is returned.
        /// </summary>
        /// <param name="keyValues">The values of the primary key for the entity to be found.</param>
        /// <returns>The entity found, or null.</returns>
        TEntity Find(params object[] keyValues);

        /// <summary>
        /// Inserts a new entity into the repository.
        /// </summary>
        /// <param name="entity">Entity to insert.</param>
        void Insert(TEntity entity);

        /// <summary>
        /// Updates an existing entity in the repository.
        /// </summary>
        /// <param name="entity">Entity to update.</param>
        void Update(TEntity entity);

        /// <summary>
        /// Removes an entity from the respository.
        /// </summary>
        /// <param name="keyValues">The values of the primary key for the entity to be found.</param>
        /// <returns>False if the entity does not exist in the repository, or true if successfully deleted.</returns>
        bool Delete(params object[] keyValues);

        /// <summary>
        /// Load related entities for an object graph.
        /// </summary>
        /// <param name="entity">Entity on which related entities are loaded.</param>
        void LoadRelatedEntities(TEntity entity);

        /// <summary>
        /// Load related entities for more than one object graph.
        /// </summary>
        /// <param name="entities">Entities on which related entities are loaded.</param>
        void LoadRelatedEntities(IEnumerable<TEntity> entities);
    }
}


<|start_filename|>Extensions/VS2012/Output/ProjectTemplates/Extract/TrackableWcfService/ConsoleClient/IExampleService.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Threading.Tasks;
//using $saferootprojectname$.Client.Entities.Models;

// Use this example as a guide for copying the service contract from Service.Core
// after adding a Trackable WCF Service Type.

/* 
namespace $safeprojectname$
{
    [ServiceContract(Namespace = "urn:trackable-entities:service")]
    public interface IExampleService
    {
        [OperationContract(Name = "GetProducts")]
        Task<IEnumerable<Product>> GetProductsAsync();

        [OperationContract(Name = "GetProduct")]
        Task<Product> GetProductAsync(int id);

        [OperationContract(Name = "UpdateProduct")]
        Task<Product> UpdateProductAsync(Product entity);

        [OperationContract(Name = "CreateProduct")]
        Task<Product> CreateProductAsync(Product entity);

        [OperationContract(Name = "DeleteProduct")]
        Task<bool> DeleteProductAsync(int id);
    }
}
*/


<|start_filename|>Extensions/VS2012/Source/ItemTemplates/TrackableEntities.ItemTemplates.WcfService/TrackableWcfServiceType.cs<|end_filename|>
﻿ 
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.ServiceModel;
using System.Threading.Tasks;
using TrackableEntities.EF6;
using $rootNamespace$.Models;

// NOTE: Add Trackable Entities EF Nuget package, then reference 
//       Trackable Service Entities project and System.ServiceModel.

namespace $rootnamespace$
{
    [ServiceContract(Namespace = "urn:trackable-entities:service")]
    public interface I$safeitemname$
    {
        [OperationContract]
        Task<IEnumerable<$entityName$>> Get$entitySetName$();

        [OperationContract]
        Task<$entityName$> Get$entityName$(int id);
        
        [OperationContract]
        Task<$entityName$> Update$entityName$($entityName$ entity);
        
        [OperationContract]
        Task<$entityName$> Create$entityName$($entityName$ entity);
        
        [OperationContract]
        Task<bool> Delete$entityName$(int id);
    }

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class $safeitemname$ : I$safeitemname$, IDisposable
    {
        private readonly $dbContextName$ _dbContext;

        public $safeitemname$()
        {
            _dbContext = new $dbContextName$();
        }

        public async Task<IEnumerable<$entityName$>> Get$entitySetName$()
        {
            IEnumerable<$entityName$> entities = await _dbContext.$entitySetName$
                .ToListAsync();
            return entities;
        }

        public async Task<$entityName$> Get$entityName$(int id)
        {
            $entityName$ entity = await _dbContext.$entitySetName$
                .SingleOrDefaultAsync(x => /* TODO: Insert key field */ x.Id == id);
            return entity;
        }

        public async Task<$entityName$> Update$entityName$($entityName$ entity)
        {
            try
            {
                _dbContext.ApplyChanges(entity);
                await _dbContext.SaveChangesAsync();
                entity.AcceptChanges();
                return entity;
            }
            catch (DbUpdateConcurrencyException updateEx)
            {
                throw new FaultException(updateEx.Message);
            }
        }

        public async Task<$entityName$> Create$entityName$($entityName$ entity)
        {
            _dbContext.$entitySetName$.Add(entity);
            await _dbContext.SaveChangesAsync();
            return entity;
        }

        // TODO: Accept entity concurrency property (rowversion)
        public async Task<bool> Delete$entityName$(int id)
        {
            $entityName$ entity = await _dbContext.$entitySetName$
                .SingleOrDefaultAsync(x => /* TODO: Insert key field */ x.Id == id);
            if (entity == null)
                return false;

            try
            {
                _dbContext.$entitySetName$.Attach(entity);
                _dbContext.$entitySetName$.Remove(entity);
                await _dbContext.SaveChangesAsync();
                return true;
            }
            catch (DbUpdateConcurrencyException updateEx)
            {
                throw new FaultException(updateEx.Message);
            }
        }

        public void Dispose()
        {
            var dispose = _dbContext as IDisposable;
            if (dispose != null)
            {
                _dbContext.Dispose();
            }
        }
    }
} 


<|start_filename|>Samples/VS2012/WcfSample/WcfSample.Client.Entities/Models/Category.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using TrackableEntities;
using TrackableEntities.Client;

namespace WcfSample.Client.Entities.Models
{
    [JsonObject(IsReference = true)]
    [DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
    public partial class Category : ModelBase<Category>, IEquatable<Category>, ITrackable
    {
		public Category()
		{
			this.Products = new ChangeTrackingCollection<Product>();
		}

		[DataMember]
		public int CategoryId
		{ 
			get { return _CategoryId; }
			set
			{
				if (Equals(value, _CategoryId)) return;
				_CategoryId = value;
				NotifyPropertyChanged(m => m.CategoryId);
			}
		}
		private int _CategoryId;

		[DataMember]
		public string CategoryName
		{ 
			get { return _CategoryName; }
			set
			{
				if (Equals(value, _CategoryName)) return;
				_CategoryName = value;
				NotifyPropertyChanged(m => m.CategoryName);
			}
		}
		private string _CategoryName;

		[DataMember]
		public ChangeTrackingCollection<Product> Products
		{
			get { return _Products; }
			set
			{
				if (Equals(value, _Products)) return;
				_Products = value;
				NotifyPropertyChanged(m => m.Products);
			}
		}
		private ChangeTrackingCollection<Product> _Products;

        #region Change Tracking

		[DataMember]
		public TrackingState TrackingState { get; set; }

		[DataMember]
		public ICollection<string> ModifiedProperties { get; set; }

		[JsonProperty, DataMember]
		private Guid EntityIdentifier { get; set; }

		#pragma warning disable 414

		[JsonProperty, DataMember]
		private Guid _entityIdentity = default(Guid);

		#pragma warning restore 414

		bool IEquatable<Category>.Equals(Category other)
		{
			if (EntityIdentifier != default(Guid))
				return EntityIdentifier == other.EntityIdentifier;
			return false;
		}
        #endregion
	}
}


<|start_filename|>Samples/VS2013/WcfSample/WcfSample.Service.Entities/Models/Mapping/CustomerSettingMap.cs<|end_filename|>

using System.Data.Entity.ModelConfiguration;
using System.ComponentModel.DataAnnotations.Schema;

namespace WcfSample.Client.Entities.Models.Mapping
{
    public class CustomerSettingMap : EntityTypeConfiguration<CustomerSetting>
    {
        public CustomerSettingMap()
        {
            // Primary Key
            this.HasKey(t => t.CustomerId);

            // Properties
            this.Property(t => t.CustomerId)
                .IsRequired()
                .IsFixedLength()
                .HasMaxLength(5);

            this.Property(t => t.Setting)
                .IsRequired()
                .HasMaxLength(50);

            // Table & Column Mappings
            this.ToTable("CustomerSetting");
            this.Property(t => t.CustomerId).HasColumnName("CustomerId");
            this.Property(t => t.Setting).HasColumnName("Setting");

            // Tracking Properties
			this.Ignore(t => t.TrackingState);
			this.Ignore(t => t.ModifiedProperties);
			this.Ignore(t => t.EntityIdentifier);

            // Relationships
            this.HasRequired(t => t.Customer)
                .WithOptional(t => t.CustomerSetting);

        }
    }
}


<|start_filename|>Extensions/VS2015/Output/Extract/ItemTemplates/EntityRepository/EntityRepository.cs<|end_filename|>
﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Data.Entity;
using System.Threading.Tasks;
using TrackableEntities.Patterns.EF6;
using $entitiesNamespace$;
using $baseNamespace$.Service.EF.Contexts;
using $baseNamespace$.Service.Persistence.Repositories;

namespace $rootnamespace$
{
    // NOTE: I$entityName$Repository will need to have been added to the Service.Persistence project
    
    public class $safeitemname$ : Repository<$entityName$>, I$entityName$Repository
    {
        // TODO: Match Database Context Interface type
        private readonly IDatabaseContext _context;

        // TODO: Match Database Context Interface type
        public $safeitemname$(IDatabaseContext context) : 
            base(context as DbContext)
        {
            _context = context;
        }

        public async Task<IEnumerable<$entityName$>> Get$entitySetName$()
        {
            // TODO: Add Includes for related entities if needed
            IEnumerable<$entityName$> entities = await _context.$entitySetName$
                .ToListAsync();
            return entities;
        }

        public async Task<$entityName$> Get$entityName$(int id)
        {
            // TODO: Add Includes for related entities if needed
            $entityName$ entity = await _context.$entitySetName$
                 .SingleOrDefaultAsync(t => t.$entityName$Id == id);
            return entity;
        }

        public async Task<bool> Delete$entityName$(int id)
        {
            // TODO: Add Includes for related entities if needed
            $entityName$ entity = await _context.$entitySetName$
                 .SingleOrDefaultAsync(t => t.$entityName$Id == id);
            if (entity == null) return false;
			ApplyDelete(entity);
            return true;
        }
    }
}


<|start_filename|>Source/Tests/TrackableEntities.Client.Tests.Entities/FamilyModels/Parent.cs<|end_filename|>
﻿using System.Collections.Generic;
using Newtonsoft.Json;

namespace TrackableEntities.Client.Tests.Entities.FamilyModels
{
    [JsonObject]
    public class Parent : EntityBase
    {
        public Parent() { }
        public Parent(string name)
        {
            _name = name;
        }

        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                if (value == _name) return;
                _name = value;
                NotifyPropertyChanged(() => Name);
            }
        }

        private ChangeTrackingCollection<Child> _children;
        public ChangeTrackingCollection<Child> Children
        {
            get { return _children; }
            set
            {
                if (Equals(value, _children)) return;
                _children = value;
                NotifyPropertyChanged(() => Children);
            }
        }
    }
}
