Skip to content

Commit a84dd66

Browse files
committed
ORM FUNDAMENTALS - MINIORM
1 parent cf95678 commit a84dd66

16 files changed

+1057
-0
lines changed
Binary file not shown.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel.DataAnnotations;
4+
using System.Text;
5+
6+
namespace MiniORM.App.Data.Entities
7+
{
8+
public class Department
9+
{
10+
[Key]
11+
public int Id { get; set; }
12+
13+
[Required]
14+
public string Name { get; set; }
15+
16+
public ICollection<Employee> Employees { get; }
17+
}
18+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System.Collections;
2+
using System.Collections.Generic;
3+
using System.ComponentModel.DataAnnotations;
4+
using System.ComponentModel.DataAnnotations.Schema;
5+
6+
namespace MiniORM.App.Data.Entities
7+
{
8+
public class Employee
9+
{
10+
[Key]
11+
public int Id { get; set; }
12+
13+
[Required]
14+
public string FirstName { get; set; }
15+
16+
public string MiddleName { get; set; }
17+
18+
[Required]
19+
public string LastName { get; set; }
20+
21+
public bool IsEmployed { get; set; }
22+
23+
[ForeignKey(nameof(Department))]
24+
public int DepartmentId { get; set; }
25+
26+
public Department Department { get; set; }
27+
28+
public ICollection<EmployeeProject> EmployeeProjects { get; }
29+
}
30+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System.ComponentModel.DataAnnotations;
2+
using System.ComponentModel.DataAnnotations.Schema;
3+
4+
namespace MiniORM.App.Data.Entities
5+
{
6+
public class EmployeeProject
7+
{
8+
[Key]
9+
[ForeignKey(nameof(Employee))]
10+
public int EmployeeId { get; set; }
11+
12+
[Key]
13+
[ForeignKey(nameof(Project))]
14+
public int ProjectId { get; set; }
15+
16+
public Employee Employee { get; set; }
17+
18+
public Project Project { get; set; }
19+
}
20+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel.DataAnnotations;
4+
using System.Text;
5+
6+
namespace MiniORM.App.Data.Entities
7+
{
8+
public class Project
9+
{
10+
[Key]
11+
public int Id { get; set; }
12+
13+
[Required]
14+
public string Name { get; set; }
15+
16+
public ICollection<EmployeeProject> EmployeeProjects { get; }
17+
}
18+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
namespace MiniORM.App.Data
2+
{
3+
using Entities;
4+
5+
public class SoftUniDbContextClass : DbContext
6+
{
7+
public SoftUniDbContextClass(string connectionString)
8+
: base(connectionString)
9+
{
10+
}
11+
12+
public DbSet<Employee> Employees { get; }
13+
14+
public DbSet<Department> Departments { get; }
15+
16+
public DbSet<Project> Projects { get; }
17+
18+
public DbSet<EmployeeProject> EmployeesProjects { get; }
19+
}
20+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>netcoreapp2.1</TargetFramework>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<ProjectReference Include="..\MiniORM\MiniORM.csproj" />
10+
</ItemGroup>
11+
12+
</Project>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace MiniORM.App
2+
{
3+
using Data;
4+
using Data.Entities;
5+
using System.Linq;
6+
7+
class Program
8+
{
9+
static void Main(string[] args)
10+
{
11+
string connectionParams = "Server=.; Database=MiniORM; Integrated Security=true;";
12+
13+
var context = new SoftUniDbContextClass(connectionParams);
14+
15+
var emp1 = new Employee()
16+
{
17+
FirstName = "I.",
18+
LastName = "Ivanov",
19+
DepartmentId = context.Departments.First().Id,
20+
IsEmployed = true,
21+
};
22+
23+
context.Employees.Add(emp1);
24+
context.SaveChanges();
25+
26+
var employee = context.Employees.Last();
27+
employee.FirstName = "Name";
28+
29+
context.SaveChanges();
30+
}
31+
}
32+
}

02.ORMFundamentals/MiniORM.sln

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio 15
4+
VisualStudioVersion = 15.0.27428.2037
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MiniORM", "MiniORM\MiniORM.csproj", "{86D40984-E71A-4041-ACF5-B3CC333585A6}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniORM.App", "MiniORM.App\MiniORM.App.csproj", "{1D8010BB-ED68-420D-B6F9-FA8577DC80A1}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
Release|Any CPU = Release|Any CPU
14+
EndGlobalSection
15+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
16+
{86D40984-E71A-4041-ACF5-B3CC333585A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17+
{86D40984-E71A-4041-ACF5-B3CC333585A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
18+
{86D40984-E71A-4041-ACF5-B3CC333585A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
19+
{86D40984-E71A-4041-ACF5-B3CC333585A6}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{1D8010BB-ED68-420D-B6F9-FA8577DC80A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{1D8010BB-ED68-420D-B6F9-FA8577DC80A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{1D8010BB-ED68-420D-B6F9-FA8577DC80A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{1D8010BB-ED68-420D-B6F9-FA8577DC80A1}.Release|Any CPU.Build.0 = Release|Any CPU
24+
EndGlobalSection
25+
GlobalSection(SolutionProperties) = preSolution
26+
HideSolutionNode = FALSE
27+
EndGlobalSection
28+
GlobalSection(ExtensibilityGlobals) = postSolution
29+
SolutionGuid = {D6743D14-7675-48B4-9F5E-05F2F2502747}
30+
EndGlobalSection
31+
EndGlobal
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel.DataAnnotations;
4+
using System.Linq;
5+
using System.Reflection;
6+
7+
namespace MiniORM
8+
{
9+
internal class ChangeTracker<T>
10+
where T : class, new()
11+
{
12+
private readonly List<T> allEntities;
13+
private readonly List<T> added;
14+
private readonly List<T> removed;
15+
16+
public ChangeTracker(IEnumerable<T> entities)
17+
{
18+
this.added = new List<T>();
19+
this.removed = new List<T>();
20+
21+
this.allEntities = CloneEntities(entities);
22+
}
23+
24+
public IReadOnlyCollection<T> AllEntities => this.allEntities.AsReadOnly();
25+
26+
public IReadOnlyCollection<T> Added => this.added.AsReadOnly();
27+
28+
public IReadOnlyCollection<T> Removed => this.removed.AsReadOnly();
29+
30+
public void Add(T item) => this.added.Add(item);
31+
32+
public void Remove(T item) => this.removed.Add(item);
33+
34+
private List<T> CloneEntities(IEnumerable<T> entities)
35+
{
36+
var clonedEntities = new List<T>();
37+
38+
PropertyInfo[] propertiesToClone = typeof(T).GetProperties()
39+
.Where(pi => DbContext.allowedSqlTypes.Contains(pi.PropertyType))
40+
.ToArray();
41+
42+
foreach (var entity in entities)
43+
{
44+
var clonedEntity = Activator.CreateInstance<T>();
45+
46+
foreach (var property in propertiesToClone)
47+
{
48+
var value = property.GetValue(entity);
49+
property.SetValue(clonedEntity, value);
50+
}
51+
52+
clonedEntities.Add(clonedEntity);
53+
}
54+
55+
return clonedEntities;
56+
}
57+
58+
public IEnumerable<T> GetModifiedEntities(DbSet<T> dbset)
59+
{
60+
var modifiedEntities = new List<T>();
61+
62+
var primaryKeys = typeof(T).GetProperties()
63+
.Where(pi => pi.HasAttribute<KeyAttribute>())
64+
.ToArray();
65+
66+
foreach (var proxyEntity in this.AllEntities)
67+
{
68+
var primaryKeyValues = GetPrimaryKeyValues(primaryKeys, proxyEntity).ToArray();
69+
70+
var entity = dbset.Entities
71+
.Single(e => GetPrimaryKeyValues(primaryKeys, e)
72+
.SequenceEqual(primaryKeyValues));
73+
74+
var isModified = IsModified(proxyEntity, entity);
75+
if (isModified)
76+
{
77+
modifiedEntities.Add(entity);
78+
}
79+
}
80+
81+
return modifiedEntities;
82+
}
83+
84+
private bool IsModified(T proxyEntity, T entity)
85+
{
86+
var monitoredProperties = typeof(T).GetProperties()
87+
.Where(pi => DbContext.allowedSqlTypes.Contains(pi.PropertyType));
88+
89+
var modifiedProperties = monitoredProperties
90+
.Where(pi => !Equals(pi.GetValue(entity), pi.GetValue(proxyEntity)))
91+
.ToArray();
92+
93+
var isModified = modifiedProperties.Any();
94+
95+
return isModified;
96+
}
97+
98+
private static IEnumerable<object> GetPrimaryKeyValues(PropertyInfo[] primaryKeys, T proxyEntity)
99+
{
100+
return primaryKeys.Select(pk => pk.GetValue(proxyEntity));
101+
}
102+
}
103+
}

0 commit comments

Comments
 (0)