├── EFExamples.Sql ├── FileGroups │ ├── EmployeeDocuments.sql │ └── EmployeeProfileImages.sql ├── Tables │ ├── FileType.sql │ ├── DocumentType.sql │ ├── __EFMigrationsHistory.sql │ ├── Vendor.sql │ ├── Company.sql │ ├── EmployeeDocument.sql │ ├── FileDescription.sql │ ├── Department.sql │ ├── DepartmentContractor.sql │ ├── Contractor.sql │ └── Employee.sql └── EFExamples.Sql.sqlproj ├── EFExamples.Api ├── appsettings.json ├── appsettings.Development.json ├── EFExamples.Api.csproj ├── Program.cs ├── Controllers │ └── ValuesController.cs └── Startup.cs ├── EFExamples.Models ├── Entities │ ├── DocumentType.cs │ ├── Vendor.cs │ ├── EmployeeDocument.cs │ ├── Entity.cs │ ├── Company.cs │ ├── FileDescription.cs │ ├── DepartmentContractor.cs │ ├── Department.cs │ ├── Contractor.cs │ └── Employee.cs ├── EFExamples.Models.csproj └── ValueTypes │ ├── PersonName.cs │ ├── Address.cs │ └── ValueObject.cs ├── README.md ├── EFExamples.Data ├── Configuration │ ├── DocumentTypeConfiguration.cs │ ├── VendorConfiguration.cs │ ├── EmployeeDocumentConfiguration.cs │ ├── EntityConfiguration.cs │ ├── DepartmentContractorConfiguration.cs │ ├── FileDescriptionConfiguration.cs │ ├── CompanyConfiguration.cs │ ├── DepartmentConfiguration.cs │ ├── ContractorConfiguration.cs │ └── EmployeeConfiguration.cs ├── DataConstants.cs ├── Queries │ └── EmployeeQuery.cs ├── Projections │ └── EmployeeProjection.cs ├── Commands │ └── EmployeeCommand.cs ├── EFExamples.Data.csproj ├── AssemblyInfo.cs ├── EFExamplesDbContext.cs └── Migrations │ ├── 20190127160330_InitialCreate.cs │ ├── EFExamplesDbContextModelSnapshot.cs │ └── 20190127160330_InitialCreate.Designer.cs ├── EFExamples.Tests ├── EFExamples.Tests.csproj ├── EmployeeTests.cs ├── ModelFakes.cs ├── ValueObjectTests.cs ├── InMemoryDbTests.cs └── DataGenerator.cs ├── EFExamples.sln └── .gitignore /EFExamples.Sql/FileGroups/EmployeeDocuments.sql: -------------------------------------------------------------------------------- 1 | ALTER DATABASE [$(DatabaseName)] 2 | ADD FILEGROUP [EmployeeDocuments] CONTAINS FILESTREAM 3 | -------------------------------------------------------------------------------- /EFExamples.Sql/FileGroups/EmployeeProfileImages.sql: -------------------------------------------------------------------------------- 1 | 2 | ALTER DATABASE [$(DatabaseName)] 3 | ADD FILEGROUP [EmployeeProfileImages] CONTAINS FILESTREAM 4 | -------------------------------------------------------------------------------- /EFExamples.Api/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "AllowedHosts": "*" 8 | } 9 | -------------------------------------------------------------------------------- /EFExamples.Models/Entities/DocumentType.cs: -------------------------------------------------------------------------------- 1 | namespace EFExamples.Models.Entities 2 | { 3 | public class DocumentType : Entity 4 | { 5 | public string Name { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /EFExamples.Models/EFExamples.Models.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /EFExamples.Api/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /EFExamples.Sql/Tables/FileType.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[FileType] 2 | ( 3 | [Id] INT NOT NULL PRIMARY KEY, 4 | [DateCreated] DATETIME2 (2) DEFAULT (sysdatetime()) NOT NULL, 5 | [DateUpdated] DATETIME2 (2) NULL, 6 | [Name] VARCHAR(300) NOT NULL 7 | ) 8 | -------------------------------------------------------------------------------- /EFExamples.Sql/Tables/DocumentType.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[DocumentType] 2 | ( 3 | [Id] INT NOT NULL IDENTITY PRIMARY KEY, 4 | [Name] VARCHAR(300) NOT NULL DEFAULT (''), 5 | [DateCreated] DATETIME2 (2) DEFAULT (sysdatetime()) NOT NULL, 6 | [DateUpdated] DATETIME2 (2) NULL, 7 | ) 8 | -------------------------------------------------------------------------------- /EFExamples.Sql/Tables/__EFMigrationsHistory.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[__EFMigrationsHistory] ( 2 | [MigrationId] NVARCHAR (150) NOT NULL, 3 | [ProductVersion] NVARCHAR (32) NOT NULL, 4 | CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY CLUSTERED ([MigrationId] ASC) 5 | ); 6 | 7 | -------------------------------------------------------------------------------- /EFExamples.Models/Entities/Vendor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EFExamples.Models.Entities 6 | { 7 | public class Vendor : Entity 8 | { 9 | public string Name { get; set; } 10 | 11 | public ICollection Contractors { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /EFExamples.Sql/Tables/Vendor.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[Vendor] ( 2 | [Id] INT IDENTITY (1, 1) NOT NULL, 3 | [DateCreated] DATETIME2 (2) DEFAULT (sysdatetime()) NOT NULL, 4 | [DateUpdated] DATETIME2 (2) NULL, 5 | [Name] NVARCHAR (300) DEFAULT (N'') NULL, 6 | CONSTRAINT [PK_Vendor] PRIMARY KEY CLUSTERED ([Id] ASC) 7 | ); 8 | 9 | -------------------------------------------------------------------------------- /EFExamples.Sql/Tables/Company.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[Company] ( 2 | [Id] INT IDENTITY (1, 1) NOT NULL, 3 | [DateCreated] DATETIME2 (2) DEFAULT (sysdatetime()) NOT NULL, 4 | [DateUpdated] DATETIME2 (2) NULL, 5 | [Name] NVARCHAR (300) DEFAULT (N'') NULL, 6 | CONSTRAINT [PK_Company] PRIMARY KEY CLUSTERED ([Id] ASC) 7 | ); 8 | 9 | -------------------------------------------------------------------------------- /EFExamples.Models/Entities/EmployeeDocument.cs: -------------------------------------------------------------------------------- 1 | namespace EFExamples.Models.Entities 2 | { 3 | public class EmployeeDocument 4 | { 5 | public int FileDescriptionId { get; set; } 6 | public int EmployeeId { get; set; } 7 | 8 | public Employee Employee { get; set; } 9 | public FileDescription FileDescription { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /EFExamples.Models/Entities/Entity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EFExamples.Models.Entities 6 | { 7 | public abstract class Entity 8 | { 9 | public int Id { get; set; } 10 | public DateTime DateCreated { get; set; } 11 | public DateTime? DateUpdated { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /EFExamples.Models/Entities/Company.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EFExamples.Models.Entities 6 | { 7 | public class Company : Entity 8 | { 9 | public string Name { get; set; } 10 | 11 | public ICollection Employees { get; set; } 12 | public ICollection Departments { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /EFExamples.Models/Entities/FileDescription.cs: -------------------------------------------------------------------------------- 1 | namespace EFExamples.Models.Entities 2 | { 3 | public class FileDescription : Entity 4 | { 5 | public int DocumentTypeId { get; set; } 6 | public string ContentType { get; set; } 7 | public string Description { get; set; } 8 | public string FileName { get; set; } 9 | 10 | public DocumentType DocumentType { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /EFExamples.Models/Entities/DepartmentContractor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EFExamples.Models.Entities 6 | { 7 | public class DepartmentContractor 8 | { 9 | public int ContractorId { get; set; } 10 | public int DepartmentId { get; set; } 11 | 12 | public Contractor Contractor { get; set; } 13 | public Department Department { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /EFExamples.Sql/Tables/EmployeeDocument.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[EmployeeDocument] 2 | ( 3 | [EmployeeId] INT NOT NULL, 4 | [FileDescriptionId] INT NOT NULL, 5 | CONSTRAINT [FK_EmployeeDocument_Employee_EmployeeId] FOREIGN KEY ([EmployeeId]) REFERENCES [Employee]([Id]), 6 | CONSTRAINT [FK_EmployeeDocument_FileDescription_FileDescriptionId] FOREIGN KEY ([FileDescriptionId]) REFERENCES [FileDescription]([Id]), 7 | CONSTRAINT [PK_EmployeeDocument] PRIMARY KEY ([EmployeeId], [FileDescriptionId]) 8 | ) 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Entity Framework Core Examples 2 | Examples for working with Entity Framework Core 3 | **Value Objects**: https://edgesidesolutions.com/ddd-value-objects-with-entity-framework-core/ 4 | **Sql Server Guid Index**: https://edgesidesolutions.com/index-sql-server-guid-column/ 5 | **CQRS with Entity Framework Core**: https://edgesidesolutions.com/cqrs-with-entity-framework-core/ 6 | **Testing with Entity Framework Core**: https://edgesidesolutions.com/testing-with-entity-framework-core/ 7 | -------------------------------------------------------------------------------- /EFExamples.Api/EFExamples.Api.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /EFExamples.Data/Configuration/DocumentTypeConfiguration.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Models.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | 4 | namespace EFExamples.Data.Configuration 5 | { 6 | public class DocumentTypeConfiguration : EntityConfiguration 7 | { 8 | public override void Configure(EntityTypeBuilder builder) 9 | { 10 | builder.Property(p => p.Name).HasMaxLength(300); 11 | 12 | base.Configure(builder); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /EFExamples.Data/DataConstants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EFExamples.Data 6 | { 7 | public class DataConstants 8 | { 9 | public class SqlServer 10 | { 11 | public const string NewId = "newid()"; 12 | public const string SysDateTime = "sysdatetime()"; 13 | public const string NewSequentialId = "newsequentialid()"; 14 | public const string DateTime2 = "datetime2(2)"; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /EFExamples.Models/Entities/Department.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EFExamples.Models.Entities 6 | { 7 | public class Department : Entity 8 | { 9 | public int CompanyId { get; set; } 10 | 11 | public string Name { get; set; } 12 | 13 | public Company Company { get; set; } 14 | public ICollection DepartmentContractors { get; set; } 15 | public ICollection Employees { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /EFExamples.Sql/Tables/FileDescription.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[FileDescription] 2 | ( 3 | [Id] INT NOT NULL IDENTITY PRIMARY KEY, 4 | [DocumentTypeId] INT NOT NULL, 5 | [ContentType] VARCHAR(150) NOT NULL DEFAULT(''), 6 | [Description] VARCHAR(400) NOT NULL DEFAULT(''), 7 | [FileName] VARCHAR(400) NOT NULL DEFAULT(''), 8 | [DateCreated] DATETIME2 (2) DEFAULT (sysdatetime()) NOT NULL, 9 | [DateUpdated] DATETIME2 (2) NULL 10 | CONSTRAINT [FK_FileDescription_DocumentType_DocumentTypeId] FOREIGN KEY ([DocumentTypeId]) REFERENCES [DocumentType]([Id]) 11 | ) 12 | -------------------------------------------------------------------------------- /EFExamples.Models/Entities/Contractor.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Models.ValueTypes; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace EFExamples.Models.Entities 7 | { 8 | public class Contractor : Entity 9 | { 10 | public int VendorId { get; set; } 11 | 12 | public Address Address { get; set; } 13 | public DateTime DateOfBirth { get; set; } 14 | public PersonName Name { get; set; } 15 | 16 | public ICollection DepartmentContractors { get; set; } 17 | public Vendor Vendor { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /EFExamples.Data/Queries/EmployeeQuery.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Models.Entities; 2 | using Microsoft.EntityFrameworkCore; 3 | using System; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | using System.Threading.Tasks; 7 | 8 | namespace EFExamples.Data.Queries 9 | { 10 | public static class EmployeeQuery 11 | { 12 | public static async Task GetEmployeeByIdAsync(this DbSet employeeDbSet, Expression> projection, int employeeId) 13 | { 14 | return await employeeDbSet.Where(m => m.Id == employeeId).Select(projection).FirstOrDefaultAsync(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /EFExamples.Sql/Tables/Department.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[Department] ( 2 | [Id] INT IDENTITY (1, 1) NOT NULL, 3 | [DateCreated] DATETIME2 (2) DEFAULT (sysdatetime()) NOT NULL, 4 | [DateUpdated] DATETIME2 (2) NULL, 5 | [CompanyId] INT NOT NULL, 6 | [Name] NVARCHAR (300) DEFAULT (N'') NULL, 7 | CONSTRAINT [PK_Department] PRIMARY KEY CLUSTERED ([Id] ASC), 8 | CONSTRAINT [FK_Department_Company_CompanyId] FOREIGN KEY ([CompanyId]) REFERENCES [dbo].[Company] ([Id]) ON DELETE CASCADE 9 | ); 10 | 11 | 12 | GO 13 | CREATE NONCLUSTERED INDEX [IX_Department_CompanyId] 14 | ON [dbo].[Department]([CompanyId] ASC); 15 | 16 | -------------------------------------------------------------------------------- /EFExamples.Api/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace EFExamples.Api 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | CreateWebHostBuilder(args).Build().Run(); 18 | } 19 | 20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 21 | WebHost.CreateDefaultBuilder(args) 22 | .UseStartup(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /EFExamples.Sql/Tables/DepartmentContractor.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[DepartmentContractor] ( 2 | [ContractorId] INT NOT NULL, 3 | [DepartmentId] INT NOT NULL, 4 | CONSTRAINT [PK_DepartmentContractor] PRIMARY KEY CLUSTERED ([ContractorId] ASC, [DepartmentId] ASC), 5 | CONSTRAINT [FK_DepartmentContractor_Contractor_ContractorId] FOREIGN KEY ([ContractorId]) REFERENCES [dbo].[Contractor] ([Id]) ON DELETE CASCADE, 6 | CONSTRAINT [FK_DepartmentContractor_Department_DepartmentId] FOREIGN KEY ([DepartmentId]) REFERENCES [dbo].[Department] ([Id]) ON DELETE CASCADE 7 | ); 8 | 9 | 10 | GO 11 | CREATE NONCLUSTERED INDEX [IX_DepartmentContractor_DepartmentId] 12 | ON [dbo].[DepartmentContractor]([DepartmentId] ASC); 13 | 14 | -------------------------------------------------------------------------------- /EFExamples.Models/Entities/Employee.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Models.ValueTypes; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace EFExamples.Models.Entities 6 | { 7 | public class Employee : Entity 8 | { 9 | public int CompanyId { get; set; } 10 | public int DepartmentId { get; set; } 11 | public Guid EmployeeId { get; private set; } 12 | 13 | public Address Address { get; set; } 14 | public DateTime DateOfBirth { get; set; } 15 | public PersonName Name { get; set; } 16 | 17 | public Company Company { get; set; } 18 | public Department Department { get; set; } 19 | public ICollection EmployeeDocuments { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /EFExamples.Data/Configuration/VendorConfiguration.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Models.Entities; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace EFExamples.Data.Configuration 9 | { 10 | public class VendorConfiguration : EntityConfiguration 11 | { 12 | public override void Configure(EntityTypeBuilder builder) 13 | { 14 | builder.Property(p => p.Name).HasMaxLength(300).HasDefaultValue(""); 15 | 16 | builder.HasMany(m => m.Contractors).WithOne(m => m.Vendor).HasForeignKey(k => k.VendorId); 17 | 18 | base.Configure(builder); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /EFExamples.Data/Configuration/EmployeeDocumentConfiguration.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Models.Entities; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 4 | 5 | namespace EFExamples.Data.Configuration 6 | { 7 | public class EmployeeDocumentConfiguration : IEntityTypeConfiguration 8 | { 9 | public void Configure(EntityTypeBuilder builder) 10 | { 11 | builder.HasKey(m => new { m.EmployeeId, m.FileDescriptionId }); 12 | builder.HasOne(m => m.Employee).WithMany(m => m.EmployeeDocuments).HasForeignKey(k => k.EmployeeId); 13 | builder.HasOne(m => m.FileDescription).WithMany().HasForeignKey(k => k.FileDescriptionId); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /EFExamples.Data/Projections/EmployeeProjection.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Models.Entities; 2 | using System; 3 | using System.Linq.Expressions; 4 | 5 | namespace EFExamples.Data.Projections 6 | { 7 | public static class EmployeeProjection 8 | { 9 | public static Expression> EmployeeWithoutDocuments 10 | { 11 | get 12 | { 13 | return m => new 14 | { 15 | m.Name, 16 | m.Company, 17 | m.Address, 18 | m.EmployeeId, 19 | m.Id, 20 | m.DepartmentId, 21 | m.Department, 22 | m.CompanyId 23 | }; 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /EFExamples.Data/Configuration/EntityConfiguration.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Models; 2 | using EFExamples.Models.Entities; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace EFExamples.Data.Configuration 10 | { 11 | public abstract class EntityConfiguration : IEntityTypeConfiguration 12 | where T : Entity 13 | { 14 | public virtual void Configure(EntityTypeBuilder builder) 15 | { 16 | builder.Property(m => m.DateCreated).HasColumnType(DataConstants.SqlServer.DateTime2).HasDefaultValueSql(DataConstants.SqlServer.SysDateTime); 17 | builder.Property(p => p.DateUpdated).HasColumnType(DataConstants.SqlServer.DateTime2); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /EFExamples.Tests/EFExamples.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /EFExamples.Data/Commands/EmployeeCommand.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Models.Entities; 2 | using EFExamples.Models.ValueTypes; 3 | using Microsoft.EntityFrameworkCore; 4 | using System.Threading.Tasks; 5 | 6 | namespace EFExamples.Data.Commands 7 | { 8 | public static class EmployeeCommand 9 | { 10 | public static async Task UpdateEmployee(this DbSet employeeDbSet, Employee employee) 11 | { 12 | var existingEmployee = await employeeDbSet.FirstOrDefaultAsync(m => m.Id == employee.Id); 13 | existingEmployee.Name = new PersonName(employee.Name.FirstName, employee.Name.LastName); 14 | existingEmployee.Address = new Address(employee.Address.StreetAddress, employee.Address.City, employee.Address.State, employee.Address.ZipCode); 15 | existingEmployee.DateOfBirth = employee.DateOfBirth; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /EFExamples.Data/Configuration/DepartmentContractorConfiguration.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Models.Entities; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace EFExamples.Data.Configuration 9 | { 10 | public class DepartmentContractorConfiguration : IEntityTypeConfiguration 11 | { 12 | public void Configure(EntityTypeBuilder builder) 13 | { 14 | builder.HasKey(m => new { m.ContractorId, m.DepartmentId }); 15 | builder.HasOne(m => m.Contractor).WithMany(m => m.DepartmentContractors).HasForeignKey(k => k.ContractorId); 16 | builder.HasOne(m => m.Department).WithMany(m => m.DepartmentContractors).HasForeignKey(k => k.DepartmentId); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /EFExamples.Data/Configuration/FileDescriptionConfiguration.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Models.Entities; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 4 | 5 | namespace EFExamples.Data.Configuration 6 | { 7 | public class FileDescriptionConfiguration : EntityConfiguration 8 | { 9 | public override void Configure(EntityTypeBuilder builder) 10 | { 11 | builder.Property(p => p.ContentType).HasDefaultValue("").HasMaxLength(300); 12 | builder.Property(p => p.Description).HasDefaultValue("").HasMaxLength(1500); 13 | builder.Property(p => p.FileName).HasDefaultValue("").HasMaxLength(250); 14 | builder.HasOne(m => m.DocumentType).WithMany().HasForeignKey(k => k.DocumentTypeId); 15 | 16 | base.Configure(builder); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /EFExamples.Data/Configuration/CompanyConfiguration.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Models; 2 | using EFExamples.Models.Entities; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace EFExamples.Data.Configuration 10 | { 11 | public class CompanyConfiguration : EntityConfiguration 12 | { 13 | public override void Configure(EntityTypeBuilder builder) 14 | { 15 | builder.Property(p => p.Name).HasMaxLength(300).HasDefaultValue(""); 16 | 17 | builder.HasMany(m => m.Employees).WithOne(m => m.Company).HasForeignKey(k => k.CompanyId); 18 | builder.HasMany(m => m.Departments).WithOne(m => m.Company).HasForeignKey(k => k.CompanyId); 19 | 20 | base.Configure(builder); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /EFExamples.Models/ValueTypes/PersonName.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EFExamples.Models.ValueTypes 6 | { 7 | public class PersonName : ValueObject 8 | { 9 | public string FirstName { get; private set; } 10 | public string FullName 11 | { 12 | get 13 | { 14 | return $"{FirstName} {LastName}"; 15 | } 16 | } 17 | public string LastName { get; private set; } 18 | 19 | private PersonName() 20 | { 21 | 22 | } 23 | 24 | public PersonName(string firstName, string lastName) 25 | { 26 | FirstName = firstName; 27 | LastName = lastName; 28 | } 29 | 30 | protected override IEnumerable GetEqualityComponents() 31 | { 32 | yield return FirstName; 33 | yield return LastName; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /EFExamples.Sql/Tables/Contractor.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[Contractor] ( 2 | [Id] INT IDENTITY (1, 1) NOT NULL, 3 | [DateCreated] DATETIME2 (2) DEFAULT (sysdatetime()) NOT NULL, 4 | [DateUpdated] DATETIME2 (2) NULL, 5 | [VendorId] INT NOT NULL, 6 | [StreetAddress] NVARCHAR (600) DEFAULT (N'') NULL, 7 | [City] NVARCHAR (150) DEFAULT (N'') NULL, 8 | [State] NVARCHAR (60) DEFAULT (N'') NULL, 9 | [ZipCode] NVARCHAR (12) DEFAULT (N'') NULL, 10 | [DateOfBirth] DATETIME2 (7) NOT NULL, 11 | [FirstName] NVARCHAR (300) DEFAULT (N'') NULL, 12 | [LastName] NVARCHAR (300) DEFAULT (N'') NULL, 13 | CONSTRAINT [PK_Contractor] PRIMARY KEY CLUSTERED ([Id] ASC), 14 | CONSTRAINT [FK_Contractor_Vendor_VendorId] FOREIGN KEY ([VendorId]) REFERENCES [dbo].[Vendor] ([Id]) 15 | ); 16 | 17 | 18 | GO 19 | CREATE NONCLUSTERED INDEX [IX_Contractor_VendorId] 20 | ON [dbo].[Contractor]([VendorId] ASC); 21 | 22 | -------------------------------------------------------------------------------- /EFExamples.Tests/EmployeeTests.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Data; 2 | using EFExamples.Data.Projections; 3 | using EFExamples.Data.Queries; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | using System.Threading.Tasks; 6 | 7 | namespace EFExamples.Tests 8 | { 9 | [TestClass] 10 | public class EmployeeTests 11 | { 12 | public static EFExamplesDbContext dbContext; 13 | 14 | [ClassInitialize] 15 | public static void ClassInitialize(TestContext context) 16 | { 17 | dbContext = new EFExamplesDbContext(); 18 | } 19 | 20 | [ClassCleanup] 21 | public static void ClassCleanUp() 22 | { 23 | dbContext.Dispose(); 24 | } 25 | 26 | [TestMethod] 27 | public async Task GetEmployeeById() 28 | { 29 | var employee = await dbContext.Employee.GetEmployeeByIdAsync(EmployeeProjection.EmployeeWithoutDocuments, 300); 30 | 31 | Assert.AreEqual(300, employee.Id); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /EFExamples.Data/Configuration/DepartmentConfiguration.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Models; 2 | using EFExamples.Models.Entities; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace EFExamples.Data.Configuration 10 | { 11 | public class DepartmentConfiguration : EntityConfiguration 12 | { 13 | public override void Configure(EntityTypeBuilder builder) 14 | { 15 | builder.Property(p => p.Name).HasMaxLength(300).HasDefaultValue(""); 16 | 17 | builder.HasOne(m => m.Company).WithMany(m => m.Departments).HasForeignKey(k => k.CompanyId); 18 | builder.HasMany(m => m.Employees).WithOne(m => m.Department).HasForeignKey(k => k.DepartmentId); 19 | builder.HasMany(m => m.DepartmentContractors).WithOne(m => m.Department).HasForeignKey(k => k.DepartmentId); 20 | 21 | base.Configure(builder); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /EFExamples.Data/EFExamples.Data.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | 7 | true 8 | 9 | 10 | 11 | 12 | all 13 | runtime; build; native; contentfiles; analyzers 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | System 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /EFExamples.Models/ValueTypes/Address.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EFExamples.Models.ValueTypes 6 | { 7 | public class Address : ValueObject 8 | { 9 | public string StreetAddress { get; private set; } 10 | public string City { get; private set; } 11 | public string State { get; private set; } 12 | public string ZipCode { get; private set; } 13 | 14 | private Address() 15 | { 16 | 17 | } 18 | 19 | public Address(string streetAddress, string city, string state, string zipCode) 20 | { 21 | StreetAddress = streetAddress; 22 | City = city; 23 | State = state; 24 | ZipCode = zipCode; 25 | } 26 | 27 | protected override IEnumerable GetEqualityComponents() 28 | { 29 | yield return StreetAddress; 30 | yield return City; 31 | yield return State; 32 | yield return ZipCode; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /EFExamples.Data/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyCopyright("Copyright © 2019")] 10 | [assembly: AssemblyTrademark("")] 11 | [assembly: AssemblyCulture("")] 12 | 13 | // Setting ComVisible to false makes the types in this assembly not visible 14 | // to COM components. If you need to access a type in this assembly from 15 | // COM, set the ComVisible attribute to true on that type. 16 | [assembly: ComVisible(false)] 17 | 18 | // The following GUID is for the ID of the typelib if this project is exposed to COM 19 | [assembly: Guid("b6eea113-7c60-4edc-a8c3-d6358746f6a9")] 20 | 21 | // Version information for an assembly consists of the following four values: 22 | // 23 | // Major Version 24 | // Minor Version 25 | // Build Number 26 | // Revision 27 | // 28 | [assembly: InternalsVisibleTo("EFExamples.Tests")] 29 | -------------------------------------------------------------------------------- /EFExamples.Api/Controllers/ValuesController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace EFExamples.Api.Controllers 8 | { 9 | [Route("api/[controller]")] 10 | [ApiController] 11 | public class ValuesController : ControllerBase 12 | { 13 | // GET api/values 14 | [HttpGet] 15 | public ActionResult> Get() 16 | { 17 | return new string[] { "value1", "value2" }; 18 | } 19 | 20 | // GET api/values/5 21 | [HttpGet("{id}")] 22 | public ActionResult Get(int id) 23 | { 24 | return "value"; 25 | } 26 | 27 | // POST api/values 28 | [HttpPost] 29 | public void Post([FromBody] string value) 30 | { 31 | } 32 | 33 | // PUT api/values/5 34 | [HttpPut("{id}")] 35 | public void Put(int id, [FromBody] string value) 36 | { 37 | } 38 | 39 | // DELETE api/values/5 40 | [HttpDelete("{id}")] 41 | public void Delete(int id) 42 | { 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /EFExamples.Api/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.AspNetCore.HttpsPolicy; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | using Microsoft.Extensions.Logging; 12 | using Microsoft.Extensions.Options; 13 | 14 | namespace EFExamples.Api 15 | { 16 | public class Startup 17 | { 18 | public Startup(IConfiguration configuration) 19 | { 20 | Configuration = configuration; 21 | } 22 | 23 | public IConfiguration Configuration { get; } 24 | 25 | public void ConfigureServices(IServiceCollection services) 26 | { 27 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); 28 | } 29 | 30 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) 31 | { 32 | if (env.IsDevelopment()) 33 | { 34 | app.UseDeveloperExceptionPage(); 35 | } 36 | else 37 | { 38 | app.UseHsts(); 39 | } 40 | 41 | app.UseHttpsRedirection(); 42 | app.UseMvc(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /EFExamples.Sql/Tables/Employee.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[Employee] ( 2 | [Id] INT IDENTITY (1, 1) NOT NULL, 3 | [DateCreated] DATETIME2 (2) DEFAULT (sysdatetime()) NOT NULL, 4 | [DateUpdated] DATETIME2 (2) NULL, 5 | [CompanyId] INT NOT NULL, 6 | [DepartmentId] INT NOT NULL, 7 | [EmployeeId] UNIQUEIDENTIFIER DEFAULT (newsequentialid()) NOT NULL, 8 | [StreetAddress] NVARCHAR (600) DEFAULT (N'') NULL, 9 | [City] NVARCHAR (150) DEFAULT (N'') NULL, 10 | [State] NVARCHAR (60) DEFAULT (N'') NULL, 11 | [ZipCode] NVARCHAR (12) DEFAULT (N'') NULL, 12 | [DateOfBirth] DATETIME2 (7) NOT NULL, 13 | [FirstName] NVARCHAR (300) DEFAULT (N'') NULL, 14 | [LastName] NVARCHAR (300) DEFAULT (N'') NULL, 15 | CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED ([Id] ASC), 16 | CONSTRAINT [FK_Employee_Company_CompanyId] FOREIGN KEY ([CompanyId]) REFERENCES [dbo].[Company] ([Id]), 17 | CONSTRAINT [FK_Employee_Department_DepartmentId] FOREIGN KEY ([DepartmentId]) REFERENCES [dbo].[Department] ([Id]) 18 | ); 19 | 20 | 21 | GO 22 | CREATE NONCLUSTERED INDEX [IX_Employee_CompanyId] 23 | ON [dbo].[Employee]([CompanyId] ASC); 24 | 25 | 26 | GO 27 | CREATE NONCLUSTERED INDEX [IX_Employee_DepartmentId] 28 | ON [dbo].[Employee]([DepartmentId] ASC); 29 | 30 | 31 | GO 32 | CREATE NONCLUSTERED INDEX [IX_Employee_EmployeeId] 33 | ON [dbo].[Employee]([EmployeeId] ASC); 34 | 35 | -------------------------------------------------------------------------------- /EFExamples.Models/ValueTypes/ValueObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace EFExamples.Models.ValueTypes 7 | { 8 | //Taken from https://enterprisecraftsmanship.com/2017/08/28/value-object-a-better-implementation/ 9 | public abstract class ValueObject 10 | { 11 | protected abstract IEnumerable GetEqualityComponents(); 12 | 13 | public override bool Equals(object obj) 14 | { 15 | if (obj == null) 16 | return false; 17 | 18 | if (GetType() != obj.GetType()) 19 | throw new ArgumentException($"Invalid comparison of Value Objects of different types: {GetType()} and {obj.GetType()}"); 20 | 21 | var valueObject = (ValueObject)obj; 22 | 23 | return GetEqualityComponents().SequenceEqual(valueObject.GetEqualityComponents()); 24 | } 25 | 26 | public override int GetHashCode() 27 | { 28 | return GetEqualityComponents() 29 | .Aggregate(1, (current, obj) => 30 | { 31 | return HashCode.Combine(current, obj); 32 | }); 33 | } 34 | 35 | public static bool operator ==(ValueObject a, ValueObject b) 36 | { 37 | if (ReferenceEquals(a, null) && ReferenceEquals(b, null)) 38 | return true; 39 | 40 | if (ReferenceEquals(a, null) || ReferenceEquals(b, null)) 41 | return false; 42 | 43 | return a.Equals(b); 44 | } 45 | 46 | public static bool operator !=(ValueObject a, ValueObject b) 47 | { 48 | return !(a == b); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /EFExamples.Data/Configuration/ContractorConfiguration.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Models.Entities; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace EFExamples.Data.Configuration 9 | { 10 | public class ContractorConfiguration : EntityConfiguration 11 | { 12 | public override void Configure(EntityTypeBuilder builder) 13 | { 14 | builder.OwnsOne(m => m.Name, a => 15 | { 16 | a.Property(p => p.FirstName).HasMaxLength(300) 17 | .HasColumnName("FirstName") 18 | .HasDefaultValue(""); 19 | a.Property(p => p.LastName).HasMaxLength(300) 20 | .HasColumnName("LastName") 21 | .HasDefaultValue(""); 22 | a.Ignore(p => p.FullName); 23 | }); 24 | builder.OwnsOne(m => m.Address, a => 25 | { 26 | a.Property(p => p.StreetAddress).HasMaxLength(600) 27 | .HasColumnName("StreetAddress") 28 | .HasDefaultValue(""); 29 | a.Property(p => p.City).HasMaxLength(150) 30 | .HasColumnName("City") 31 | .HasDefaultValue(""); 32 | a.Property(p => p.State).HasMaxLength(60) 33 | .HasColumnName("State") 34 | .HasDefaultValue(""); 35 | a.Property(p => p.ZipCode).HasMaxLength(12) 36 | .HasColumnName("ZipCode") 37 | .HasDefaultValue(""); 38 | }); 39 | 40 | builder.HasMany(m => m.DepartmentContractors).WithOne(m => m.Contractor) 41 | .HasForeignKey(k => k.ContractorId); 42 | builder.HasOne(m => m.Vendor).WithMany(m => m.Contractors) 43 | .OnDelete(DeleteBehavior.Restrict) 44 | .HasForeignKey(k => k.VendorId); 45 | 46 | base.Configure(builder); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /EFExamples.Tests/ModelFakes.cs: -------------------------------------------------------------------------------- 1 | using Bogus; 2 | using EFExamples.Models; 3 | using EFExamples.Models.Entities; 4 | using EFExamples.Models.ValueTypes; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace EFExamples.Tests 10 | { 11 | public static class ModelFakes 12 | { 13 | public static Faker CompanyFake { get; set; } 14 | public static Faker ContractorFake { get; set; } 15 | public static Faker EmployeeFake { get; set; } 16 | public static Faker VendorFake { get; set; } 17 | 18 | static ModelFakes() 19 | { 20 | BuildCompanyFaker(); 21 | BuildContractorFaker(); 22 | BuildEmployeeFaker(); 23 | BuildVendorFaker(); 24 | } 25 | 26 | private static void BuildCompanyFaker() 27 | { 28 | CompanyFake = new Faker(); 29 | CompanyFake.RuleFor(m => m.Name, r => r.Company.CompanyName()); 30 | } 31 | 32 | public static void BuildContractorFaker() 33 | { 34 | ContractorFake = new Faker(); 35 | ContractorFake.RuleFor(m => m.Name, r => new PersonName(r.Name.FirstName(), r.Name.LastName())); 36 | ContractorFake.RuleFor(m => m.Address, r => new Address(r.Address.StreetAddress(), r.Address.City(), r.Address.State(), r.Address.ZipCode())); 37 | ContractorFake.RuleFor(m => m.DateOfBirth, r => r.Person.DateOfBirth.Date); 38 | } 39 | 40 | 41 | private static void BuildEmployeeFaker() 42 | { 43 | EmployeeFake = new Faker(); 44 | EmployeeFake.RuleFor(m => m.Name, r => new PersonName(r.Name.FirstName(), r.Name.LastName())); 45 | EmployeeFake.RuleFor(m => m.Address, r => new Address(r.Address.StreetAddress(), r.Address.City(), r.Address.State(), r.Address.ZipCode())); 46 | EmployeeFake.RuleFor(m => m.DateOfBirth, r => r.Person.DateOfBirth.Date); 47 | } 48 | 49 | private static void BuildVendorFaker() 50 | { 51 | VendorFake = new Faker(); 52 | VendorFake.RuleFor(m => m.Name, r => r.Company.CompanyName()); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /EFExamples.Data/Configuration/EmployeeConfiguration.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Models.Entities; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 4 | 5 | namespace EFExamples.Data.Configuration 6 | { 7 | public class EmployeeConfiguration : EntityConfiguration 8 | { 9 | public override void Configure(EntityTypeBuilder builder) 10 | { 11 | builder.OwnsOne(m => m.Name, a => 12 | { 13 | a.Property(p => p.FirstName).HasMaxLength(300) 14 | .HasColumnName("FirstName") 15 | .HasDefaultValue(""); 16 | a.Property(p => p.LastName).HasMaxLength(300) 17 | .HasColumnName("LastName") 18 | .HasDefaultValue(""); 19 | a.Ignore(p => p.FullName); 20 | }); 21 | builder.OwnsOne(m => m.Address, a => 22 | { 23 | a.Property(p => p.StreetAddress).HasMaxLength(600) 24 | .HasColumnName("StreetAddress") 25 | .HasDefaultValue(""); 26 | a.Property(p => p.City).HasMaxLength(150) 27 | .HasColumnName("City") 28 | .HasDefaultValue(""); 29 | a.Property(p => p.State).HasMaxLength(60) 30 | .HasColumnName("State") 31 | .HasDefaultValue(""); 32 | a.Property(p => p.ZipCode).HasMaxLength(12) 33 | .HasColumnName("ZipCode") 34 | .HasDefaultValue(""); 35 | }); 36 | builder.Property(p => p.EmployeeId).HasDefaultValueSql(DataConstants.SqlServer.NewSequentialId); 37 | builder.HasIndex(p => p.EmployeeId).HasName("IX_Employee_EmployeeId").ForSqlServerIsClustered(false); 38 | 39 | builder.HasOne(m => m.Company).WithMany(m => m.Employees) 40 | .OnDelete(DeleteBehavior.Restrict) 41 | .HasForeignKey(k => k.CompanyId); 42 | builder.HasOne(m => m.Department).WithMany(m => m.Employees) 43 | .OnDelete(DeleteBehavior.Restrict) 44 | .HasForeignKey(k => k.DepartmentId); 45 | builder.HasMany(m => m.EmployeeDocuments).WithOne(m => m.Employee).HasForeignKey(k => k.EmployeeId); 46 | 47 | base.Configure(builder); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /EFExamples.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.168 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFExamples.Models", "EFExamples.Models\EFExamples.Models.csproj", "{14B8C934-8D8D-4B9D-B991-0993A5A35A7D}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFExamples.Data", "EFExamples.Data\EFExamples.Data.csproj", "{CCDC14D0-7004-4DE8-BAA9-492C16983DBD}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFExamples.Tests", "EFExamples.Tests\EFExamples.Tests.csproj", "{4CF06D0B-057F-4A5B-8F78-657B4594BC4C}" 11 | EndProject 12 | Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "EFExamples.Sql", "EFExamples.Sql\EFExamples.Sql.sqlproj", "{317FA827-CB30-4881-8B7F-B60D59096AEA}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFExamples.Api", "EFExamples.Api\EFExamples.Api.csproj", "{A6ED8BB2-6384-45F2-9878-CDA45E4B43A5}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {14B8C934-8D8D-4B9D-B991-0993A5A35A7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {14B8C934-8D8D-4B9D-B991-0993A5A35A7D}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {14B8C934-8D8D-4B9D-B991-0993A5A35A7D}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {14B8C934-8D8D-4B9D-B991-0993A5A35A7D}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {CCDC14D0-7004-4DE8-BAA9-492C16983DBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {CCDC14D0-7004-4DE8-BAA9-492C16983DBD}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {CCDC14D0-7004-4DE8-BAA9-492C16983DBD}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {CCDC14D0-7004-4DE8-BAA9-492C16983DBD}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {4CF06D0B-057F-4A5B-8F78-657B4594BC4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {4CF06D0B-057F-4A5B-8F78-657B4594BC4C}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {4CF06D0B-057F-4A5B-8F78-657B4594BC4C}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {4CF06D0B-057F-4A5B-8F78-657B4594BC4C}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {317FA827-CB30-4881-8B7F-B60D59096AEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {317FA827-CB30-4881-8B7F-B60D59096AEA}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {317FA827-CB30-4881-8B7F-B60D59096AEA}.Debug|Any CPU.Deploy.0 = Debug|Any CPU 37 | {317FA827-CB30-4881-8B7F-B60D59096AEA}.Release|Any CPU.ActiveCfg = Release|Any CPU 38 | {317FA827-CB30-4881-8B7F-B60D59096AEA}.Release|Any CPU.Build.0 = Release|Any CPU 39 | {317FA827-CB30-4881-8B7F-B60D59096AEA}.Release|Any CPU.Deploy.0 = Release|Any CPU 40 | {A6ED8BB2-6384-45F2-9878-CDA45E4B43A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {A6ED8BB2-6384-45F2-9878-CDA45E4B43A5}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {A6ED8BB2-6384-45F2-9878-CDA45E4B43A5}.Release|Any CPU.ActiveCfg = Release|Any CPU 43 | {A6ED8BB2-6384-45F2-9878-CDA45E4B43A5}.Release|Any CPU.Build.0 = Release|Any CPU 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {A444FE2D-EDF6-4561-B353-15EE2CC1EEBF} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /EFExamples.Tests/ValueObjectTests.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Data; 2 | using EFExamples.Models.Entities; 3 | using EFExamples.Models.ValueTypes; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | 10 | namespace EFExamples.Tests 11 | { 12 | [TestClass] 13 | public class ValueObjectTests 14 | { 15 | private static EFExamplesDbContext dbContext; 16 | 17 | [ClassInitialize] 18 | public static void ClassInitialize(TestContext context) 19 | { 20 | dbContext = new EFExamplesDbContext(); 21 | } 22 | 23 | [ClassCleanup] 24 | public static void ClassCleanUp() 25 | { 26 | dbContext.Dispose(); 27 | } 28 | 29 | [TestMethod] 30 | public void GetOwnedValueObjectsForEmployees() 31 | { 32 | var employees = dbContext.Employee.Take(10).ToList(); 33 | 34 | foreach(var employee in employees) 35 | { 36 | Assert.IsNotNull(employee.Address.City); 37 | Assert.IsNotNull(employee.Address.State); 38 | Assert.IsNotNull(employee.Address.StreetAddress); 39 | Assert.IsNotNull(employee.Address.ZipCode); 40 | Assert.IsNotNull(employee.Name.FirstName); 41 | Assert.IsNotNull(employee.Name.LastName); 42 | Assert.IsNotNull(employee.Name.FullName); 43 | } 44 | } 45 | 46 | [TestMethod] 47 | public void GetOwnedValueObjectsForContractors() 48 | { 49 | var contractors = dbContext.Contractor.Take(10).ToList(); 50 | 51 | foreach (var contractor in contractors) 52 | { 53 | Assert.IsNotNull(contractor.Address.City); 54 | Assert.IsNotNull(contractor.Address.State); 55 | Assert.IsNotNull(contractor.Address.StreetAddress); 56 | Assert.IsNotNull(contractor.Address.ZipCode); 57 | Assert.IsNotNull(contractor.Name.FirstName); 58 | Assert.IsNotNull(contractor.Name.LastName); 59 | Assert.IsNotNull(contractor.Name.FullName); 60 | } 61 | } 62 | 63 | [TestMethod] 64 | public void AddNewContractor() 65 | { 66 | var contractor = ModelFakes.ContractorFake.Generate(); 67 | var vendor = dbContext.Vendor.FirstOrDefault(); 68 | contractor.VendorId = vendor.Id; 69 | dbContext.Contractor.Add(contractor); 70 | dbContext.SaveChanges(); 71 | 72 | Assert.AreNotEqual(0, contractor.Id); 73 | } 74 | 75 | [TestMethod] 76 | public void UpdateContractorAddress() 77 | { 78 | var contractor = dbContext.Contractor.FirstOrDefault(); 79 | contractor.Address = ModelFakes.ContractorFake.Generate().Address; 80 | dbContext.Contractor.Update(contractor); 81 | dbContext.SaveChanges(); 82 | dbContext.DetachAllEntities(); 83 | 84 | var updatedContractor = dbContext.Contractor.FirstOrDefault(m => m.Id == contractor.Id); 85 | var areEqual = contractor.Address == updatedContractor.Address; 86 | Assert.IsTrue(areEqual); 87 | } 88 | 89 | [TestMethod] 90 | public void CheckValueObjectEquality() 91 | { 92 | var address1 = ModelFakes.ContractorFake.Generate().Address; 93 | var address2 = ModelFakes.ContractorFake.Generate().Address; 94 | 95 | Assert.IsFalse(address1 == address2); 96 | 97 | var address3 = new Address(address1.StreetAddress, address1.City, address1.State, address1.ZipCode); 98 | 99 | Assert.IsTrue(address1 == address3); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /EFExamples.Data/EFExamplesDbContext.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Data.Configuration; 2 | using EFExamples.Models.Entities; 3 | using Microsoft.EntityFrameworkCore; 4 | using System; 5 | using System.Linq; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace EFExamples.Data 10 | { 11 | public class EFExamplesDbContext : DbContext 12 | { 13 | public EFExamplesDbContext() 14 | { 15 | } 16 | 17 | public EFExamplesDbContext(DbContextOptions options) : base(options) { } 18 | 19 | public virtual DbSet Company { get; set; } 20 | public virtual DbSet Contractor { get; set; } 21 | public virtual DbSet Department { get; set; } 22 | public virtual DbSet DepartmentContractor { get; set; } 23 | public virtual DbSet DocumentType { get; set; } 24 | public virtual DbSet Employee { get; set; } 25 | public virtual DbSet EmployeeDocument { get; set; } 26 | public virtual DbSet FileDescription { get; set; } 27 | public virtual DbSet Vendor { get; set; } 28 | 29 | protected override void OnModelCreating(ModelBuilder builder) 30 | { 31 | builder.ApplyConfiguration(new CompanyConfiguration()); 32 | builder.ApplyConfiguration(new ContractorConfiguration()); 33 | builder.ApplyConfiguration(new DepartmentConfiguration()); 34 | builder.ApplyConfiguration(new DepartmentContractorConfiguration()); 35 | builder.ApplyConfiguration(new DocumentTypeConfiguration()); 36 | builder.ApplyConfiguration(new EmployeeConfiguration()); 37 | builder.ApplyConfiguration(new EmployeeDocumentConfiguration()); 38 | builder.ApplyConfiguration(new FileDescriptionConfiguration()); 39 | builder.ApplyConfiguration(new VendorConfiguration()); 40 | } 41 | 42 | protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 43 | { 44 | var connectionString = @"Data Source=DESKTOP-J803PRQ;Initial Catalog=EFExamples;Integrated Security=True;Persist Security Info=False;Pooling=False;MultipleActiveResultSets=False;Connect Timeout=60;Encrypt=False;TrustServerCertificate=True"; 45 | optionsBuilder.UseSqlServer(connectionString); 46 | 47 | base.OnConfiguring(optionsBuilder); 48 | } 49 | 50 | public override int SaveChanges() 51 | { 52 | AddAuditValues(); 53 | 54 | return base.SaveChanges(); 55 | } 56 | 57 | public void DetachAllEntities() 58 | { 59 | var changedEntriesCopy = ChangeTracker.Entries() 60 | .Where(e => e.State == EntityState.Added || 61 | e.State == EntityState.Modified || 62 | e.State == EntityState.Deleted) 63 | .ToList(); 64 | 65 | foreach (var entry in changedEntriesCopy) 66 | entry.State = EntityState.Detached; 67 | } 68 | 69 | public override Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken)) 70 | { 71 | AddAuditValues(); 72 | 73 | return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); 74 | } 75 | 76 | private void AddAuditValues() 77 | { 78 | var entities = ChangeTracker.Entries().Where(x => (x.Entity is Entity) 79 | && (x.State == EntityState.Added || x.State == EntityState.Detached || x.State == EntityState.Modified)); 80 | 81 | foreach (var entity in entities) 82 | { 83 | if (entity.Entity is Entity) 84 | { 85 | if (entity.State == EntityState.Added) 86 | { 87 | ((Entity)entity.Entity).DateCreated = DateTime.Now; 88 | } 89 | 90 | if (entity.State == EntityState.Modified) 91 | { 92 | ((Entity)entity.Entity).DateUpdated = DateTime.Now; 93 | } 94 | } 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /EFExamples.Sql/EFExamples.Sql.sqlproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | EFExamples.Sql 8 | 2.0 9 | 4.1 10 | {317fa827-cb30-4881-8b7f-b60d59096aea} 11 | Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider 12 | Database 13 | 14 | 15 | EFExamples.Sql 16 | EFExamples.Sql 17 | 1033,CI 18 | BySchemaAndSchemaType 19 | True 20 | v4.5 21 | CS 22 | Properties 23 | False 24 | True 25 | True 26 | SQL_Latin1_General_CP1_CI_AS 27 | PRIMARY 28 | 29 | 30 | bin\Release\ 31 | $(MSBuildProjectName).sql 32 | False 33 | pdbonly 34 | true 35 | false 36 | true 37 | prompt 38 | 4 39 | 40 | 41 | bin\Debug\ 42 | $(MSBuildProjectName).sql 43 | false 44 | true 45 | full 46 | false 47 | true 48 | true 49 | prompt 50 | 4 51 | 52 | 53 | 11.0 54 | 55 | True 56 | 11.0 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /EFExamples.Tests/InMemoryDbTests.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Data; 2 | using EFExamples.Models.Entities; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace EFExamples.Tests 10 | { 11 | [TestClass] 12 | public class InMemoryDbTests 13 | { 14 | 15 | private static EFExamplesDbContext dbContext; 16 | private static readonly List departmentNames = new List 17 | { 18 | "HR", 19 | "Accounting", 20 | "Legal", 21 | "IT", 22 | "Customer Service", 23 | "Sales" 24 | }; 25 | private static readonly int numberOfCompanies = 3; 26 | private static readonly int numberOfContractorsPerDepartment = 5; 27 | private static readonly int numberOfContractorsPerVendor = 10; 28 | private static readonly int numberOfEmployeesPerDepartment = 25; 29 | private static readonly int numberOfVendorsPerCompany = 3; 30 | private static readonly Random random = new Random(); 31 | private static readonly List documentTypeIds = new List { 1, 2, 3 }; 32 | 33 | [ClassInitialize] 34 | public static void Initialize(TestContext testContext) 35 | { 36 | var options = new DbContextOptionsBuilder() 37 | .UseInMemoryDatabase(Guid.NewGuid().ToString()) 38 | .Options; 39 | var context = new EFExamplesDbContext(options); 40 | 41 | var companies = new List(); 42 | var vendors = new List(); 43 | 44 | for (var i = 0; i < numberOfCompanies; i++) 45 | { 46 | var companyFake = ModelFakes.CompanyFake.Generate(); 47 | dbContext.Company.Add(companyFake); 48 | companies.Add(companyFake); 49 | } 50 | 51 | dbContext.SaveChanges(); 52 | 53 | foreach (var company in companies) 54 | { 55 | for (var i = 0; i < numberOfVendorsPerCompany; i++) 56 | { 57 | var vendor = ModelFakes.VendorFake.Generate(); 58 | vendor.Contractors = new List(); 59 | 60 | for (var c = 0; c < numberOfContractorsPerVendor; c++) 61 | { 62 | var contractor = ModelFakes.ContractorFake.Generate(); 63 | vendor.Contractors.Add(contractor); 64 | } 65 | 66 | dbContext.Vendor.Add(vendor); 67 | vendors.Add(vendor); 68 | } 69 | 70 | dbContext.SaveChanges(); 71 | 72 | foreach (var departmentName in departmentNames) 73 | { 74 | var department = new Department 75 | { 76 | Name = departmentName, 77 | DateCreated = DateTime.Now, 78 | DateUpdated = DateTime.Now, 79 | CompanyId = company.Id, 80 | Employees = new List(), 81 | DepartmentContractors = new List() 82 | }; 83 | 84 | for (var i = 0; i < numberOfEmployeesPerDepartment; i++) 85 | { 86 | var employee = ModelFakes.EmployeeFake.Generate(); 87 | employee.CompanyId = company.Id; 88 | employee.EmployeeDocuments = new List 89 | { 90 | new EmployeeDocument 91 | { 92 | FileDescription = new FileDescription 93 | { 94 | ContentType = ".PDF", 95 | FileName = "Test File", 96 | Description = "File description", 97 | DocumentTypeId = documentTypeIds.ElementAt(random.Next(documentTypeIds.Count)) 98 | } 99 | } 100 | }; 101 | department.Employees.Add(employee); 102 | } 103 | 104 | var vendor = vendors[random.Next(vendors.Count)]; 105 | 106 | for (var v = 0; v < numberOfContractorsPerDepartment; v++) 107 | { 108 | var contractor = vendor.Contractors.ElementAt(random.Next(vendor.Contractors.Count)); 109 | 110 | if (!department.DepartmentContractors.Any(m => m.ContractorId == contractor.Id)) 111 | department.DepartmentContractors.Add(new DepartmentContractor 112 | { 113 | ContractorId = contractor.Id 114 | }); 115 | else 116 | v--; 117 | } 118 | 119 | dbContext.Department.Add(department); 120 | } 121 | 122 | dbContext.SaveChanges(); 123 | } 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /EFExamples.Tests/DataGenerator.cs: -------------------------------------------------------------------------------- 1 | using EFExamples.Data; 2 | using EFExamples.Models.Entities; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace EFExamples.Tests 10 | { 11 | [TestClass] 12 | public class DataGenerator 13 | { 14 | private static EFExamplesDbContext dbContext; 15 | private readonly List departmentNames = new List 16 | { 17 | "HR", 18 | "Accounting", 19 | "Legal", 20 | "IT", 21 | "Customer Service", 22 | "Sales" 23 | }; 24 | private readonly int numberOfCompanies = 3; 25 | private readonly int numberOfContractorsPerDepartment = 5; 26 | private readonly int numberOfContractorsPerVendor = 10; 27 | private readonly int numberOfEmployeesPerDepartment = 25; 28 | private readonly int numberOfVendorsPerCompany = 3; 29 | private readonly Random random = new Random(); 30 | private readonly List documentTypeIds = new List { 1, 2, 3 }; 31 | 32 | [ClassInitialize] 33 | public static void ClassInitialize(TestContext context) 34 | { 35 | dbContext = new EFExamplesDbContext(); 36 | } 37 | 38 | [ClassCleanup] 39 | public static void ClassCleanUp() 40 | { 41 | dbContext.Dispose(); 42 | } 43 | 44 | 45 | [TestMethod] 46 | public void AddFileTypes() 47 | { 48 | var documentTypes = new List 49 | { 50 | new DocumentType 51 | { 52 | Name = "Invoice" 53 | }, 54 | new DocumentType 55 | { 56 | Name = "References" 57 | }, 58 | new DocumentType 59 | { 60 | Name = "Form I9" 61 | } 62 | }; 63 | 64 | dbContext.DocumentType.AddRange(documentTypes); 65 | dbContext.SaveChanges(); 66 | } 67 | 68 | [TestMethod] 69 | public void AddDocumentsToExistingEmployees() 70 | { 71 | var employees = dbContext.Employee.Include(m => m.EmployeeDocuments).ToList(); 72 | 73 | foreach (var employee in employees) 74 | { 75 | employee.EmployeeDocuments.Add(new EmployeeDocument 76 | { 77 | FileDescription = new FileDescription 78 | { 79 | ContentType = ".PDF", 80 | FileName = "Test File", 81 | Description = "File description", 82 | DocumentTypeId = documentTypeIds.ElementAt(random.Next(documentTypeIds.Count)) 83 | } 84 | }); 85 | } 86 | 87 | dbContext.SaveChanges(); 88 | } 89 | 90 | [TestMethod] 91 | public void GenerateData() 92 | { 93 | var companies = new List(); 94 | var vendors = new List(); 95 | 96 | for (var i = 0; i < numberOfCompanies; i++) 97 | { 98 | var companyFake = ModelFakes.CompanyFake.Generate(); 99 | dbContext.Company.Add(companyFake); 100 | companies.Add(companyFake); 101 | } 102 | 103 | dbContext.SaveChanges(); 104 | 105 | foreach (var company in companies) 106 | { 107 | for (var i = 0; i < numberOfVendorsPerCompany; i++) 108 | { 109 | var vendor = ModelFakes.VendorFake.Generate(); 110 | vendor.Contractors = new List(); 111 | 112 | for (var c = 0; c < numberOfContractorsPerVendor; c++) 113 | { 114 | var contractor = ModelFakes.ContractorFake.Generate(); 115 | vendor.Contractors.Add(contractor); 116 | } 117 | 118 | dbContext.Vendor.Add(vendor); 119 | vendors.Add(vendor); 120 | } 121 | 122 | dbContext.SaveChanges(); 123 | 124 | foreach (var departmentName in departmentNames) 125 | { 126 | var department = new Department 127 | { 128 | Name = departmentName, 129 | DateCreated = DateTime.Now, 130 | DateUpdated = DateTime.Now, 131 | CompanyId = company.Id, 132 | Employees = new List(), 133 | DepartmentContractors = new List() 134 | }; 135 | 136 | for (var i = 0; i < numberOfEmployeesPerDepartment; i++) 137 | { 138 | var employee = ModelFakes.EmployeeFake.Generate(); 139 | employee.CompanyId = company.Id; 140 | employee.EmployeeDocuments = new List 141 | { 142 | new EmployeeDocument 143 | { 144 | FileDescription = new FileDescription 145 | { 146 | ContentType = ".PDF", 147 | FileName = "Test File", 148 | Description = "File description", 149 | DocumentTypeId = documentTypeIds.ElementAt(random.Next(documentTypeIds.Count)) 150 | } 151 | } 152 | }; 153 | department.Employees.Add(employee); 154 | } 155 | 156 | var vendor = vendors[random.Next(vendors.Count)]; 157 | 158 | for (var v = 0; v < numberOfContractorsPerDepartment; v++) 159 | { 160 | var contractor = vendor.Contractors.ElementAt(random.Next(vendor.Contractors.Count)); 161 | 162 | if (!department.DepartmentContractors.Any(m => m.ContractorId == contractor.Id)) 163 | department.DepartmentContractors.Add(new DepartmentContractor 164 | { 165 | ContractorId = contractor.Id 166 | }); 167 | else 168 | v--; 169 | } 170 | 171 | dbContext.Department.Add(department); 172 | } 173 | 174 | dbContext.SaveChanges(); 175 | } 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /EFExamples.Data/Migrations/20190127160330_InitialCreate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Metadata; 3 | using Microsoft.EntityFrameworkCore.Migrations; 4 | 5 | namespace EFExamples.Data.Migrations 6 | { 7 | public partial class InitialCreate : Migration 8 | { 9 | protected override void Up(MigrationBuilder migrationBuilder) 10 | { 11 | migrationBuilder.CreateTable( 12 | name: "Company", 13 | columns: table => new 14 | { 15 | Id = table.Column(nullable: false) 16 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 17 | DateCreated = table.Column(type: "datetime2(2)", nullable: false, defaultValueSql: "sysdatetime()"), 18 | DateUpdated = table.Column(type: "datetime2(2)", nullable: true), 19 | Name = table.Column(maxLength: 300, nullable: true, defaultValue: "") 20 | }, 21 | constraints: table => 22 | { 23 | table.PrimaryKey("PK_Company", x => x.Id); 24 | }); 25 | 26 | migrationBuilder.CreateTable( 27 | name: "Vendor", 28 | columns: table => new 29 | { 30 | Id = table.Column(nullable: false) 31 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 32 | DateCreated = table.Column(type: "datetime2(2)", nullable: false, defaultValueSql: "sysdatetime()"), 33 | DateUpdated = table.Column(type: "datetime2(2)", nullable: true), 34 | Name = table.Column(maxLength: 300, nullable: true, defaultValue: "") 35 | }, 36 | constraints: table => 37 | { 38 | table.PrimaryKey("PK_Vendor", x => x.Id); 39 | }); 40 | 41 | migrationBuilder.CreateTable( 42 | name: "Department", 43 | columns: table => new 44 | { 45 | Id = table.Column(nullable: false) 46 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 47 | DateCreated = table.Column(type: "datetime2(2)", nullable: false, defaultValueSql: "sysdatetime()"), 48 | DateUpdated = table.Column(type: "datetime2(2)", nullable: true), 49 | CompanyId = table.Column(nullable: false), 50 | Name = table.Column(maxLength: 300, nullable: true, defaultValue: "") 51 | }, 52 | constraints: table => 53 | { 54 | table.PrimaryKey("PK_Department", x => x.Id); 55 | table.ForeignKey( 56 | name: "FK_Department_Company_CompanyId", 57 | column: x => x.CompanyId, 58 | principalTable: "Company", 59 | principalColumn: "Id", 60 | onDelete: ReferentialAction.Cascade); 61 | }); 62 | 63 | migrationBuilder.CreateTable( 64 | name: "Contractor", 65 | columns: table => new 66 | { 67 | Id = table.Column(nullable: false) 68 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 69 | DateCreated = table.Column(type: "datetime2(2)", nullable: false, defaultValueSql: "sysdatetime()"), 70 | DateUpdated = table.Column(type: "datetime2(2)", nullable: true), 71 | VendorId = table.Column(nullable: false), 72 | StreetAddress = table.Column(maxLength: 600, nullable: true, defaultValue: ""), 73 | City = table.Column(maxLength: 150, nullable: true, defaultValue: ""), 74 | State = table.Column(maxLength: 60, nullable: true, defaultValue: ""), 75 | ZipCode = table.Column(maxLength: 12, nullable: true, defaultValue: ""), 76 | DateOfBirth = table.Column(nullable: false), 77 | FirstName = table.Column(maxLength: 300, nullable: true, defaultValue: ""), 78 | LastName = table.Column(maxLength: 300, nullable: true, defaultValue: "") 79 | }, 80 | constraints: table => 81 | { 82 | table.PrimaryKey("PK_Contractor", x => x.Id); 83 | table.ForeignKey( 84 | name: "FK_Contractor_Vendor_VendorId", 85 | column: x => x.VendorId, 86 | principalTable: "Vendor", 87 | principalColumn: "Id", 88 | onDelete: ReferentialAction.Restrict); 89 | }); 90 | 91 | migrationBuilder.CreateTable( 92 | name: "Employee", 93 | columns: table => new 94 | { 95 | Id = table.Column(nullable: false) 96 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 97 | DateCreated = table.Column(type: "datetime2(2)", nullable: false, defaultValueSql: "sysdatetime()"), 98 | DateUpdated = table.Column(type: "datetime2(2)", nullable: true), 99 | CompanyId = table.Column(nullable: false), 100 | DepartmentId = table.Column(nullable: false), 101 | EmployeeId = table.Column(nullable: false, defaultValueSql: "newsequentialid()"), 102 | StreetAddress = table.Column(maxLength: 600, nullable: true, defaultValue: ""), 103 | City = table.Column(maxLength: 150, nullable: true, defaultValue: ""), 104 | State = table.Column(maxLength: 60, nullable: true, defaultValue: ""), 105 | ZipCode = table.Column(maxLength: 12, nullable: true, defaultValue: ""), 106 | DateOfBirth = table.Column(nullable: false), 107 | FirstName = table.Column(maxLength: 300, nullable: true, defaultValue: ""), 108 | LastName = table.Column(maxLength: 300, nullable: true, defaultValue: "") 109 | }, 110 | constraints: table => 111 | { 112 | table.PrimaryKey("PK_Employee", x => x.Id); 113 | table.ForeignKey( 114 | name: "FK_Employee_Company_CompanyId", 115 | column: x => x.CompanyId, 116 | principalTable: "Company", 117 | principalColumn: "Id", 118 | onDelete: ReferentialAction.Restrict); 119 | table.ForeignKey( 120 | name: "FK_Employee_Department_DepartmentId", 121 | column: x => x.DepartmentId, 122 | principalTable: "Department", 123 | principalColumn: "Id", 124 | onDelete: ReferentialAction.Restrict); 125 | }); 126 | 127 | migrationBuilder.CreateTable( 128 | name: "DepartmentContractor", 129 | columns: table => new 130 | { 131 | ContractorId = table.Column(nullable: false), 132 | DepartmentId = table.Column(nullable: false) 133 | }, 134 | constraints: table => 135 | { 136 | table.PrimaryKey("PK_DepartmentContractor", x => new { x.ContractorId, x.DepartmentId }); 137 | table.ForeignKey( 138 | name: "FK_DepartmentContractor_Contractor_ContractorId", 139 | column: x => x.ContractorId, 140 | principalTable: "Contractor", 141 | principalColumn: "Id", 142 | onDelete: ReferentialAction.Cascade); 143 | table.ForeignKey( 144 | name: "FK_DepartmentContractor_Department_DepartmentId", 145 | column: x => x.DepartmentId, 146 | principalTable: "Department", 147 | principalColumn: "Id", 148 | onDelete: ReferentialAction.Cascade); 149 | }); 150 | 151 | migrationBuilder.CreateIndex( 152 | name: "IX_Contractor_VendorId", 153 | table: "Contractor", 154 | column: "VendorId"); 155 | 156 | migrationBuilder.CreateIndex( 157 | name: "IX_Department_CompanyId", 158 | table: "Department", 159 | column: "CompanyId"); 160 | 161 | migrationBuilder.CreateIndex( 162 | name: "IX_DepartmentContractor_DepartmentId", 163 | table: "DepartmentContractor", 164 | column: "DepartmentId"); 165 | 166 | migrationBuilder.CreateIndex( 167 | name: "IX_Employee_CompanyId", 168 | table: "Employee", 169 | column: "CompanyId"); 170 | 171 | migrationBuilder.CreateIndex( 172 | name: "IX_Employee_DepartmentId", 173 | table: "Employee", 174 | column: "DepartmentId"); 175 | 176 | migrationBuilder.CreateIndex( 177 | name: "IX_Employee_EmployeeId", 178 | table: "Employee", 179 | column: "EmployeeId") 180 | .Annotation("SqlServer:Clustered", false); 181 | } 182 | 183 | protected override void Down(MigrationBuilder migrationBuilder) 184 | { 185 | migrationBuilder.DropTable( 186 | name: "DepartmentContractor"); 187 | 188 | migrationBuilder.DropTable( 189 | name: "Employee"); 190 | 191 | migrationBuilder.DropTable( 192 | name: "Contractor"); 193 | 194 | migrationBuilder.DropTable( 195 | name: "Department"); 196 | 197 | migrationBuilder.DropTable( 198 | name: "Vendor"); 199 | 200 | migrationBuilder.DropTable( 201 | name: "Company"); 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /EFExamples.Data/Migrations/EFExamplesDbContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using EFExamples.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | 9 | namespace EFExamples.Data.Migrations 10 | { 11 | [DbContext(typeof(EFExamplesDbContext))] 12 | partial class EFExamplesDbContextModelSnapshot : ModelSnapshot 13 | { 14 | protected override void BuildModel(ModelBuilder modelBuilder) 15 | { 16 | #pragma warning disable 612, 618 17 | modelBuilder 18 | .HasAnnotation("ProductVersion", "2.2.0-rtm-35687") 19 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 20 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 21 | 22 | modelBuilder.Entity("EFExamples.Models.Entities.Company", b => 23 | { 24 | b.Property("Id") 25 | .ValueGeneratedOnAdd() 26 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 27 | 28 | b.Property("DateCreated") 29 | .ValueGeneratedOnAdd() 30 | .HasColumnType("datetime2(2)") 31 | .HasDefaultValueSql("sysdatetime()"); 32 | 33 | b.Property("DateUpdated") 34 | .HasColumnType("datetime2(2)"); 35 | 36 | b.Property("Name") 37 | .ValueGeneratedOnAdd() 38 | .HasMaxLength(300) 39 | .HasDefaultValue(""); 40 | 41 | b.HasKey("Id"); 42 | 43 | b.ToTable("Company"); 44 | }); 45 | 46 | modelBuilder.Entity("EFExamples.Models.Entities.Contractor", b => 47 | { 48 | b.Property("Id") 49 | .ValueGeneratedOnAdd() 50 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 51 | 52 | b.Property("DateCreated") 53 | .ValueGeneratedOnAdd() 54 | .HasColumnType("datetime2(2)") 55 | .HasDefaultValueSql("sysdatetime()"); 56 | 57 | b.Property("DateOfBirth"); 58 | 59 | b.Property("DateUpdated") 60 | .HasColumnType("datetime2(2)"); 61 | 62 | b.Property("VendorId"); 63 | 64 | b.HasKey("Id"); 65 | 66 | b.HasIndex("VendorId"); 67 | 68 | b.ToTable("Contractor"); 69 | }); 70 | 71 | modelBuilder.Entity("EFExamples.Models.Entities.Department", b => 72 | { 73 | b.Property("Id") 74 | .ValueGeneratedOnAdd() 75 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 76 | 77 | b.Property("CompanyId"); 78 | 79 | b.Property("DateCreated") 80 | .ValueGeneratedOnAdd() 81 | .HasColumnType("datetime2(2)") 82 | .HasDefaultValueSql("sysdatetime()"); 83 | 84 | b.Property("DateUpdated") 85 | .HasColumnType("datetime2(2)"); 86 | 87 | b.Property("Name") 88 | .ValueGeneratedOnAdd() 89 | .HasMaxLength(300) 90 | .HasDefaultValue(""); 91 | 92 | b.HasKey("Id"); 93 | 94 | b.HasIndex("CompanyId"); 95 | 96 | b.ToTable("Department"); 97 | }); 98 | 99 | modelBuilder.Entity("EFExamples.Models.Entities.DepartmentContractor", b => 100 | { 101 | b.Property("ContractorId"); 102 | 103 | b.Property("DepartmentId"); 104 | 105 | b.HasKey("ContractorId", "DepartmentId"); 106 | 107 | b.HasIndex("DepartmentId"); 108 | 109 | b.ToTable("DepartmentContractor"); 110 | }); 111 | 112 | modelBuilder.Entity("EFExamples.Models.Entities.Employee", b => 113 | { 114 | b.Property("Id") 115 | .ValueGeneratedOnAdd() 116 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 117 | 118 | b.Property("CompanyId"); 119 | 120 | b.Property("DateCreated") 121 | .ValueGeneratedOnAdd() 122 | .HasColumnType("datetime2(2)") 123 | .HasDefaultValueSql("sysdatetime()"); 124 | 125 | b.Property("DateOfBirth"); 126 | 127 | b.Property("DateUpdated") 128 | .HasColumnType("datetime2(2)"); 129 | 130 | b.Property("DepartmentId"); 131 | 132 | b.Property("EmployeeId") 133 | .ValueGeneratedOnAdd() 134 | .HasDefaultValueSql("newsequentialid()"); 135 | 136 | b.HasKey("Id"); 137 | 138 | b.HasIndex("CompanyId"); 139 | 140 | b.HasIndex("DepartmentId"); 141 | 142 | b.HasIndex("EmployeeId") 143 | .HasName("IX_Employee_EmployeeId") 144 | .HasAnnotation("SqlServer:Clustered", false); 145 | 146 | b.ToTable("Employee"); 147 | }); 148 | 149 | modelBuilder.Entity("EFExamples.Models.Entities.Vendor", b => 150 | { 151 | b.Property("Id") 152 | .ValueGeneratedOnAdd() 153 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 154 | 155 | b.Property("DateCreated") 156 | .ValueGeneratedOnAdd() 157 | .HasColumnType("datetime2(2)") 158 | .HasDefaultValueSql("sysdatetime()"); 159 | 160 | b.Property("DateUpdated") 161 | .HasColumnType("datetime2(2)"); 162 | 163 | b.Property("Name") 164 | .ValueGeneratedOnAdd() 165 | .HasMaxLength(300) 166 | .HasDefaultValue(""); 167 | 168 | b.HasKey("Id"); 169 | 170 | b.ToTable("Vendor"); 171 | }); 172 | 173 | modelBuilder.Entity("EFExamples.Models.Entities.Contractor", b => 174 | { 175 | b.HasOne("EFExamples.Models.Entities.Vendor", "Vendor") 176 | .WithMany("Contractors") 177 | .HasForeignKey("VendorId") 178 | .OnDelete(DeleteBehavior.Restrict); 179 | 180 | b.OwnsOne("EFExamples.Models.ValueTypes.Address", "Address", b1 => 181 | { 182 | b1.Property("ContractorId") 183 | .ValueGeneratedOnAdd() 184 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 185 | 186 | b1.Property("City") 187 | .ValueGeneratedOnAdd() 188 | .HasColumnName("City") 189 | .HasMaxLength(150) 190 | .HasDefaultValue(""); 191 | 192 | b1.Property("State") 193 | .ValueGeneratedOnAdd() 194 | .HasColumnName("State") 195 | .HasMaxLength(60) 196 | .HasDefaultValue(""); 197 | 198 | b1.Property("StreetAddress") 199 | .ValueGeneratedOnAdd() 200 | .HasColumnName("StreetAddress") 201 | .HasMaxLength(600) 202 | .HasDefaultValue(""); 203 | 204 | b1.Property("ZipCode") 205 | .ValueGeneratedOnAdd() 206 | .HasColumnName("ZipCode") 207 | .HasMaxLength(12) 208 | .HasDefaultValue(""); 209 | 210 | b1.HasKey("ContractorId"); 211 | 212 | b1.ToTable("Contractor"); 213 | 214 | b1.HasOne("EFExamples.Models.Entities.Contractor") 215 | .WithOne("Address") 216 | .HasForeignKey("EFExamples.Models.ValueTypes.Address", "ContractorId") 217 | .OnDelete(DeleteBehavior.Cascade); 218 | }); 219 | 220 | b.OwnsOne("EFExamples.Models.ValueTypes.PersonName", "Name", b1 => 221 | { 222 | b1.Property("ContractorId") 223 | .ValueGeneratedOnAdd() 224 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 225 | 226 | b1.Property("FirstName") 227 | .ValueGeneratedOnAdd() 228 | .HasColumnName("FirstName") 229 | .HasMaxLength(300) 230 | .HasDefaultValue(""); 231 | 232 | b1.Property("LastName") 233 | .ValueGeneratedOnAdd() 234 | .HasColumnName("LastName") 235 | .HasMaxLength(300) 236 | .HasDefaultValue(""); 237 | 238 | b1.HasKey("ContractorId"); 239 | 240 | b1.ToTable("Contractor"); 241 | 242 | b1.HasOne("EFExamples.Models.Entities.Contractor") 243 | .WithOne("Name") 244 | .HasForeignKey("EFExamples.Models.ValueTypes.PersonName", "ContractorId") 245 | .OnDelete(DeleteBehavior.Cascade); 246 | }); 247 | }); 248 | 249 | modelBuilder.Entity("EFExamples.Models.Entities.Department", b => 250 | { 251 | b.HasOne("EFExamples.Models.Entities.Company", "Company") 252 | .WithMany("Departments") 253 | .HasForeignKey("CompanyId") 254 | .OnDelete(DeleteBehavior.Cascade); 255 | }); 256 | 257 | modelBuilder.Entity("EFExamples.Models.Entities.DepartmentContractor", b => 258 | { 259 | b.HasOne("EFExamples.Models.Entities.Contractor", "Contractor") 260 | .WithMany("DepartmentContractors") 261 | .HasForeignKey("ContractorId") 262 | .OnDelete(DeleteBehavior.Cascade); 263 | 264 | b.HasOne("EFExamples.Models.Entities.Department", "Department") 265 | .WithMany("DepartmentContractors") 266 | .HasForeignKey("DepartmentId") 267 | .OnDelete(DeleteBehavior.Cascade); 268 | }); 269 | 270 | modelBuilder.Entity("EFExamples.Models.Entities.Employee", b => 271 | { 272 | b.HasOne("EFExamples.Models.Entities.Company", "Company") 273 | .WithMany("Employees") 274 | .HasForeignKey("CompanyId") 275 | .OnDelete(DeleteBehavior.Restrict); 276 | 277 | b.HasOne("EFExamples.Models.Entities.Department", "Department") 278 | .WithMany("Employees") 279 | .HasForeignKey("DepartmentId") 280 | .OnDelete(DeleteBehavior.Restrict); 281 | 282 | b.OwnsOne("EFExamples.Models.ValueTypes.Address", "Address", b1 => 283 | { 284 | b1.Property("EmployeeId") 285 | .ValueGeneratedOnAdd() 286 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 287 | 288 | b1.Property("City") 289 | .ValueGeneratedOnAdd() 290 | .HasColumnName("City") 291 | .HasMaxLength(150) 292 | .HasDefaultValue(""); 293 | 294 | b1.Property("State") 295 | .ValueGeneratedOnAdd() 296 | .HasColumnName("State") 297 | .HasMaxLength(60) 298 | .HasDefaultValue(""); 299 | 300 | b1.Property("StreetAddress") 301 | .ValueGeneratedOnAdd() 302 | .HasColumnName("StreetAddress") 303 | .HasMaxLength(600) 304 | .HasDefaultValue(""); 305 | 306 | b1.Property("ZipCode") 307 | .ValueGeneratedOnAdd() 308 | .HasColumnName("ZipCode") 309 | .HasMaxLength(12) 310 | .HasDefaultValue(""); 311 | 312 | b1.HasKey("EmployeeId"); 313 | 314 | b1.ToTable("Employee"); 315 | 316 | b1.HasOne("EFExamples.Models.Entities.Employee") 317 | .WithOne("Address") 318 | .HasForeignKey("EFExamples.Models.ValueTypes.Address", "EmployeeId") 319 | .OnDelete(DeleteBehavior.Cascade); 320 | }); 321 | 322 | b.OwnsOne("EFExamples.Models.ValueTypes.PersonName", "Name", b1 => 323 | { 324 | b1.Property("EmployeeId") 325 | .ValueGeneratedOnAdd() 326 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 327 | 328 | b1.Property("FirstName") 329 | .ValueGeneratedOnAdd() 330 | .HasColumnName("FirstName") 331 | .HasMaxLength(300) 332 | .HasDefaultValue(""); 333 | 334 | b1.Property("LastName") 335 | .ValueGeneratedOnAdd() 336 | .HasColumnName("LastName") 337 | .HasMaxLength(300) 338 | .HasDefaultValue(""); 339 | 340 | b1.HasKey("EmployeeId"); 341 | 342 | b1.ToTable("Employee"); 343 | 344 | b1.HasOne("EFExamples.Models.Entities.Employee") 345 | .WithOne("Name") 346 | .HasForeignKey("EFExamples.Models.ValueTypes.PersonName", "EmployeeId") 347 | .OnDelete(DeleteBehavior.Cascade); 348 | }); 349 | }); 350 | #pragma warning restore 612, 618 351 | } 352 | } 353 | } 354 | -------------------------------------------------------------------------------- /EFExamples.Data/Migrations/20190127160330_InitialCreate.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using EFExamples.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | namespace EFExamples.Data.Migrations 11 | { 12 | [DbContext(typeof(EFExamplesDbContext))] 13 | [Migration("20190127160330_InitialCreate")] 14 | partial class InitialCreate 15 | { 16 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("ProductVersion", "2.2.0-rtm-35687") 21 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 22 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 23 | 24 | modelBuilder.Entity("EFExamples.Models.Entities.Company", b => 25 | { 26 | b.Property("Id") 27 | .ValueGeneratedOnAdd() 28 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 29 | 30 | b.Property("DateCreated") 31 | .ValueGeneratedOnAdd() 32 | .HasColumnType("datetime2(2)") 33 | .HasDefaultValueSql("sysdatetime()"); 34 | 35 | b.Property("DateUpdated") 36 | .HasColumnType("datetime2(2)"); 37 | 38 | b.Property("Name") 39 | .ValueGeneratedOnAdd() 40 | .HasMaxLength(300) 41 | .HasDefaultValue(""); 42 | 43 | b.HasKey("Id"); 44 | 45 | b.ToTable("Company"); 46 | }); 47 | 48 | modelBuilder.Entity("EFExamples.Models.Entities.Contractor", b => 49 | { 50 | b.Property("Id") 51 | .ValueGeneratedOnAdd() 52 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 53 | 54 | b.Property("DateCreated") 55 | .ValueGeneratedOnAdd() 56 | .HasColumnType("datetime2(2)") 57 | .HasDefaultValueSql("sysdatetime()"); 58 | 59 | b.Property("DateOfBirth"); 60 | 61 | b.Property("DateUpdated") 62 | .HasColumnType("datetime2(2)"); 63 | 64 | b.Property("VendorId"); 65 | 66 | b.HasKey("Id"); 67 | 68 | b.HasIndex("VendorId"); 69 | 70 | b.ToTable("Contractor"); 71 | }); 72 | 73 | modelBuilder.Entity("EFExamples.Models.Entities.Department", b => 74 | { 75 | b.Property("Id") 76 | .ValueGeneratedOnAdd() 77 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 78 | 79 | b.Property("CompanyId"); 80 | 81 | b.Property("DateCreated") 82 | .ValueGeneratedOnAdd() 83 | .HasColumnType("datetime2(2)") 84 | .HasDefaultValueSql("sysdatetime()"); 85 | 86 | b.Property("DateUpdated") 87 | .HasColumnType("datetime2(2)"); 88 | 89 | b.Property("Name") 90 | .ValueGeneratedOnAdd() 91 | .HasMaxLength(300) 92 | .HasDefaultValue(""); 93 | 94 | b.HasKey("Id"); 95 | 96 | b.HasIndex("CompanyId"); 97 | 98 | b.ToTable("Department"); 99 | }); 100 | 101 | modelBuilder.Entity("EFExamples.Models.Entities.DepartmentContractor", b => 102 | { 103 | b.Property("ContractorId"); 104 | 105 | b.Property("DepartmentId"); 106 | 107 | b.HasKey("ContractorId", "DepartmentId"); 108 | 109 | b.HasIndex("DepartmentId"); 110 | 111 | b.ToTable("DepartmentContractor"); 112 | }); 113 | 114 | modelBuilder.Entity("EFExamples.Models.Entities.Employee", b => 115 | { 116 | b.Property("Id") 117 | .ValueGeneratedOnAdd() 118 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 119 | 120 | b.Property("CompanyId"); 121 | 122 | b.Property("DateCreated") 123 | .ValueGeneratedOnAdd() 124 | .HasColumnType("datetime2(2)") 125 | .HasDefaultValueSql("sysdatetime()"); 126 | 127 | b.Property("DateOfBirth"); 128 | 129 | b.Property("DateUpdated") 130 | .HasColumnType("datetime2(2)"); 131 | 132 | b.Property("DepartmentId"); 133 | 134 | b.Property("EmployeeId") 135 | .ValueGeneratedOnAdd() 136 | .HasDefaultValueSql("newsequentialid()"); 137 | 138 | b.HasKey("Id"); 139 | 140 | b.HasIndex("CompanyId"); 141 | 142 | b.HasIndex("DepartmentId"); 143 | 144 | b.HasIndex("EmployeeId") 145 | .HasName("IX_Employee_EmployeeId") 146 | .HasAnnotation("SqlServer:Clustered", false); 147 | 148 | b.ToTable("Employee"); 149 | }); 150 | 151 | modelBuilder.Entity("EFExamples.Models.Entities.Vendor", b => 152 | { 153 | b.Property("Id") 154 | .ValueGeneratedOnAdd() 155 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 156 | 157 | b.Property("DateCreated") 158 | .ValueGeneratedOnAdd() 159 | .HasColumnType("datetime2(2)") 160 | .HasDefaultValueSql("sysdatetime()"); 161 | 162 | b.Property("DateUpdated") 163 | .HasColumnType("datetime2(2)"); 164 | 165 | b.Property("Name") 166 | .ValueGeneratedOnAdd() 167 | .HasMaxLength(300) 168 | .HasDefaultValue(""); 169 | 170 | b.HasKey("Id"); 171 | 172 | b.ToTable("Vendor"); 173 | }); 174 | 175 | modelBuilder.Entity("EFExamples.Models.Entities.Contractor", b => 176 | { 177 | b.HasOne("EFExamples.Models.Entities.Vendor", "Vendor") 178 | .WithMany("Contractors") 179 | .HasForeignKey("VendorId") 180 | .OnDelete(DeleteBehavior.Restrict); 181 | 182 | b.OwnsOne("EFExamples.Models.ValueTypes.Address", "Address", b1 => 183 | { 184 | b1.Property("ContractorId") 185 | .ValueGeneratedOnAdd() 186 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 187 | 188 | b1.Property("City") 189 | .ValueGeneratedOnAdd() 190 | .HasColumnName("City") 191 | .HasMaxLength(150) 192 | .HasDefaultValue(""); 193 | 194 | b1.Property("State") 195 | .ValueGeneratedOnAdd() 196 | .HasColumnName("State") 197 | .HasMaxLength(60) 198 | .HasDefaultValue(""); 199 | 200 | b1.Property("StreetAddress") 201 | .ValueGeneratedOnAdd() 202 | .HasColumnName("StreetAddress") 203 | .HasMaxLength(600) 204 | .HasDefaultValue(""); 205 | 206 | b1.Property("ZipCode") 207 | .ValueGeneratedOnAdd() 208 | .HasColumnName("ZipCode") 209 | .HasMaxLength(12) 210 | .HasDefaultValue(""); 211 | 212 | b1.HasKey("ContractorId"); 213 | 214 | b1.ToTable("Contractor"); 215 | 216 | b1.HasOne("EFExamples.Models.Entities.Contractor") 217 | .WithOne("Address") 218 | .HasForeignKey("EFExamples.Models.ValueTypes.Address", "ContractorId") 219 | .OnDelete(DeleteBehavior.Cascade); 220 | }); 221 | 222 | b.OwnsOne("EFExamples.Models.ValueTypes.PersonName", "Name", b1 => 223 | { 224 | b1.Property("ContractorId") 225 | .ValueGeneratedOnAdd() 226 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 227 | 228 | b1.Property("FirstName") 229 | .ValueGeneratedOnAdd() 230 | .HasColumnName("FirstName") 231 | .HasMaxLength(300) 232 | .HasDefaultValue(""); 233 | 234 | b1.Property("LastName") 235 | .ValueGeneratedOnAdd() 236 | .HasColumnName("LastName") 237 | .HasMaxLength(300) 238 | .HasDefaultValue(""); 239 | 240 | b1.HasKey("ContractorId"); 241 | 242 | b1.ToTable("Contractor"); 243 | 244 | b1.HasOne("EFExamples.Models.Entities.Contractor") 245 | .WithOne("Name") 246 | .HasForeignKey("EFExamples.Models.ValueTypes.PersonName", "ContractorId") 247 | .OnDelete(DeleteBehavior.Cascade); 248 | }); 249 | }); 250 | 251 | modelBuilder.Entity("EFExamples.Models.Entities.Department", b => 252 | { 253 | b.HasOne("EFExamples.Models.Entities.Company", "Company") 254 | .WithMany("Departments") 255 | .HasForeignKey("CompanyId") 256 | .OnDelete(DeleteBehavior.Cascade); 257 | }); 258 | 259 | modelBuilder.Entity("EFExamples.Models.Entities.DepartmentContractor", b => 260 | { 261 | b.HasOne("EFExamples.Models.Entities.Contractor", "Contractor") 262 | .WithMany("DepartmentContractors") 263 | .HasForeignKey("ContractorId") 264 | .OnDelete(DeleteBehavior.Cascade); 265 | 266 | b.HasOne("EFExamples.Models.Entities.Department", "Department") 267 | .WithMany("DepartmentContractors") 268 | .HasForeignKey("DepartmentId") 269 | .OnDelete(DeleteBehavior.Cascade); 270 | }); 271 | 272 | modelBuilder.Entity("EFExamples.Models.Entities.Employee", b => 273 | { 274 | b.HasOne("EFExamples.Models.Entities.Company", "Company") 275 | .WithMany("Employees") 276 | .HasForeignKey("CompanyId") 277 | .OnDelete(DeleteBehavior.Restrict); 278 | 279 | b.HasOne("EFExamples.Models.Entities.Department", "Department") 280 | .WithMany("Employees") 281 | .HasForeignKey("DepartmentId") 282 | .OnDelete(DeleteBehavior.Restrict); 283 | 284 | b.OwnsOne("EFExamples.Models.ValueTypes.Address", "Address", b1 => 285 | { 286 | b1.Property("EmployeeId") 287 | .ValueGeneratedOnAdd() 288 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 289 | 290 | b1.Property("City") 291 | .ValueGeneratedOnAdd() 292 | .HasColumnName("City") 293 | .HasMaxLength(150) 294 | .HasDefaultValue(""); 295 | 296 | b1.Property("State") 297 | .ValueGeneratedOnAdd() 298 | .HasColumnName("State") 299 | .HasMaxLength(60) 300 | .HasDefaultValue(""); 301 | 302 | b1.Property("StreetAddress") 303 | .ValueGeneratedOnAdd() 304 | .HasColumnName("StreetAddress") 305 | .HasMaxLength(600) 306 | .HasDefaultValue(""); 307 | 308 | b1.Property("ZipCode") 309 | .ValueGeneratedOnAdd() 310 | .HasColumnName("ZipCode") 311 | .HasMaxLength(12) 312 | .HasDefaultValue(""); 313 | 314 | b1.HasKey("EmployeeId"); 315 | 316 | b1.ToTable("Employee"); 317 | 318 | b1.HasOne("EFExamples.Models.Entities.Employee") 319 | .WithOne("Address") 320 | .HasForeignKey("EFExamples.Models.ValueTypes.Address", "EmployeeId") 321 | .OnDelete(DeleteBehavior.Cascade); 322 | }); 323 | 324 | b.OwnsOne("EFExamples.Models.ValueTypes.PersonName", "Name", b1 => 325 | { 326 | b1.Property("EmployeeId") 327 | .ValueGeneratedOnAdd() 328 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 329 | 330 | b1.Property("FirstName") 331 | .ValueGeneratedOnAdd() 332 | .HasColumnName("FirstName") 333 | .HasMaxLength(300) 334 | .HasDefaultValue(""); 335 | 336 | b1.Property("LastName") 337 | .ValueGeneratedOnAdd() 338 | .HasColumnName("LastName") 339 | .HasMaxLength(300) 340 | .HasDefaultValue(""); 341 | 342 | b1.HasKey("EmployeeId"); 343 | 344 | b1.ToTable("Employee"); 345 | 346 | b1.HasOne("EFExamples.Models.Entities.Employee") 347 | .WithOne("Name") 348 | .HasForeignKey("EFExamples.Models.ValueTypes.PersonName", "EmployeeId") 349 | .OnDelete(DeleteBehavior.Cascade); 350 | }); 351 | }); 352 | #pragma warning restore 612, 618 353 | } 354 | } 355 | } 356 | --------------------------------------------------------------------------------