Skip to content

Commit

Permalink
ORM FUNDAMENTALS - MINIORM
Browse files Browse the repository at this point in the history
  • Loading branch information
SonicTheCat committed Feb 27, 2019
1 parent cf95678 commit a84dd66
Show file tree
Hide file tree
Showing 16 changed files with 1,057 additions and 0 deletions.
Binary file not shown.
18 changes: 18 additions & 0 deletions 02.ORMFundamentals/MiniORM.App/Data/Entities/Department.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;

namespace MiniORM.App.Data.Entities
{
public class Department
{
[Key]
public int Id { get; set; }

[Required]
public string Name { get; set; }

public ICollection<Employee> Employees { get; }
}
}
30 changes: 30 additions & 0 deletions 02.ORMFundamentals/MiniORM.App/Data/Entities/Employee.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MiniORM.App.Data.Entities
{
public class Employee
{
[Key]
public int Id { get; set; }

[Required]
public string FirstName { get; set; }

public string MiddleName { get; set; }

[Required]
public string LastName { get; set; }

public bool IsEmployed { get; set; }

[ForeignKey(nameof(Department))]
public int DepartmentId { get; set; }

public Department Department { get; set; }

public ICollection<EmployeeProject> EmployeeProjects { get; }
}
}
20 changes: 20 additions & 0 deletions 02.ORMFundamentals/MiniORM.App/Data/Entities/EmployeeProject.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MiniORM.App.Data.Entities
{
public class EmployeeProject
{
[Key]
[ForeignKey(nameof(Employee))]
public int EmployeeId { get; set; }

[Key]
[ForeignKey(nameof(Project))]
public int ProjectId { get; set; }

public Employee Employee { get; set; }

public Project Project { get; set; }
}
}
18 changes: 18 additions & 0 deletions 02.ORMFundamentals/MiniORM.App/Data/Entities/Project.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;

namespace MiniORM.App.Data.Entities
{
public class Project
{
[Key]
public int Id { get; set; }

[Required]
public string Name { get; set; }

public ICollection<EmployeeProject> EmployeeProjects { get; }
}
}
20 changes: 20 additions & 0 deletions 02.ORMFundamentals/MiniORM.App/Data/SoftUniDbContextClass.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace MiniORM.App.Data
{
using Entities;

public class SoftUniDbContextClass : DbContext
{
public SoftUniDbContextClass(string connectionString)
: base(connectionString)
{
}

public DbSet<Employee> Employees { get; }

public DbSet<Department> Departments { get; }

public DbSet<Project> Projects { get; }

public DbSet<EmployeeProject> EmployeesProjects { get; }
}
}
12 changes: 12 additions & 0 deletions 02.ORMFundamentals/MiniORM.App/MiniORM.App.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\MiniORM\MiniORM.csproj" />
</ItemGroup>

</Project>
32 changes: 32 additions & 0 deletions 02.ORMFundamentals/MiniORM.App/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
namespace MiniORM.App
{
using Data;
using Data.Entities;
using System.Linq;

class Program
{
static void Main(string[] args)
{
string connectionParams = "Server=.; Database=MiniORM; Integrated Security=true;";

var context = new SoftUniDbContextClass(connectionParams);

var emp1 = new Employee()
{
FirstName = "I.",
LastName = "Ivanov",
DepartmentId = context.Departments.First().Id,
IsEmployed = true,
};

context.Employees.Add(emp1);
context.SaveChanges();

var employee = context.Employees.Last();
employee.FirstName = "Name";

context.SaveChanges();
}
}
}
31 changes: 31 additions & 0 deletions 02.ORMFundamentals/MiniORM.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27428.2037
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MiniORM", "MiniORM\MiniORM.csproj", "{86D40984-E71A-4041-ACF5-B3CC333585A6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniORM.App", "MiniORM.App\MiniORM.App.csproj", "{1D8010BB-ED68-420D-B6F9-FA8577DC80A1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{86D40984-E71A-4041-ACF5-B3CC333585A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{86D40984-E71A-4041-ACF5-B3CC333585A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{86D40984-E71A-4041-ACF5-B3CC333585A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{86D40984-E71A-4041-ACF5-B3CC333585A6}.Release|Any CPU.Build.0 = Release|Any CPU
{1D8010BB-ED68-420D-B6F9-FA8577DC80A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1D8010BB-ED68-420D-B6F9-FA8577DC80A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1D8010BB-ED68-420D-B6F9-FA8577DC80A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1D8010BB-ED68-420D-B6F9-FA8577DC80A1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D6743D14-7675-48B4-9F5E-05F2F2502747}
EndGlobalSection
EndGlobal
103 changes: 103 additions & 0 deletions 02.ORMFundamentals/MiniORM/ChangeTracker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;

namespace MiniORM
{
internal class ChangeTracker<T>
where T : class, new()
{
private readonly List<T> allEntities;
private readonly List<T> added;
private readonly List<T> removed;

public ChangeTracker(IEnumerable<T> entities)
{
this.added = new List<T>();
this.removed = new List<T>();

this.allEntities = CloneEntities(entities);
}

public IReadOnlyCollection<T> AllEntities => this.allEntities.AsReadOnly();

public IReadOnlyCollection<T> Added => this.added.AsReadOnly();

public IReadOnlyCollection<T> Removed => this.removed.AsReadOnly();

public void Add(T item) => this.added.Add(item);

public void Remove(T item) => this.removed.Add(item);

private List<T> CloneEntities(IEnumerable<T> entities)
{
var clonedEntities = new List<T>();

PropertyInfo[] propertiesToClone = typeof(T).GetProperties()
.Where(pi => DbContext.allowedSqlTypes.Contains(pi.PropertyType))
.ToArray();

foreach (var entity in entities)
{
var clonedEntity = Activator.CreateInstance<T>();

foreach (var property in propertiesToClone)
{
var value = property.GetValue(entity);
property.SetValue(clonedEntity, value);
}

clonedEntities.Add(clonedEntity);
}

return clonedEntities;
}

public IEnumerable<T> GetModifiedEntities(DbSet<T> dbset)
{
var modifiedEntities = new List<T>();

var primaryKeys = typeof(T).GetProperties()
.Where(pi => pi.HasAttribute<KeyAttribute>())
.ToArray();

foreach (var proxyEntity in this.AllEntities)
{
var primaryKeyValues = GetPrimaryKeyValues(primaryKeys, proxyEntity).ToArray();

var entity = dbset.Entities
.Single(e => GetPrimaryKeyValues(primaryKeys, e)
.SequenceEqual(primaryKeyValues));

var isModified = IsModified(proxyEntity, entity);
if (isModified)
{
modifiedEntities.Add(entity);
}
}

return modifiedEntities;
}

private bool IsModified(T proxyEntity, T entity)
{
var monitoredProperties = typeof(T).GetProperties()
.Where(pi => DbContext.allowedSqlTypes.Contains(pi.PropertyType));

var modifiedProperties = monitoredProperties
.Where(pi => !Equals(pi.GetValue(entity), pi.GetValue(proxyEntity)))
.ToArray();

var isModified = modifiedProperties.Any();

return isModified;
}

private static IEnumerable<object> GetPrimaryKeyValues(PropertyInfo[] primaryKeys, T proxyEntity)
{
return primaryKeys.Select(pk => pk.GetValue(proxyEntity));
}
}
}
25 changes: 25 additions & 0 deletions 02.ORMFundamentals/MiniORM/ConnectionManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace MiniORM
{
using System;

/// <summary>
/// Used for wrapping a database connection with a using statement and
/// automatically closing it when the using statement ends
/// </summary>
internal class ConnectionManager : IDisposable
{
private readonly DatabaseConnection connection;

public ConnectionManager(DatabaseConnection connection)
{
this.connection = connection;

this.connection.Open();
}

public void Dispose()
{
this.connection.Close();
}
}
}
Loading

0 comments on commit a84dd66

Please sign in to comment.