GitHub-ссылка на проект
К собеседованию было дано тестовое задание:
Create a web application that will monitor changes on a SQL table using SignalR Requirements
1) The SQL table should have the following definition: CREATE TABLE DevTest( [ID] int IDENTITY(1, 1) NOT NULL, [CampaignName] varchar(255) NULL, [Date] datetime NULL, [Clicks} int NULL, [Conversions] int NULL, [Impressions] int NULL, [AffiliateName] varchar(255) NULL )
2) All data access should adhere to the repository and unit of work design patterns
3) There should be a view that implements SignalR and displays the changes to the SQL table in real time.
4) There should be a view that allows the user to make changes to the DevTest table (insert, update, delete)
, где как видите, одним из условий было использование паттерна Unit of Work
.
Вот часть моего решения (с полным решением вы можете ознакомиться по ссылке выше/в конце этого поста) касаемо UoW
:
IRepository.cs
namespace MonitDbTable.Interfaces
{
public interface IRepository<T> where T : class
{
IEnumerable<T> GetAll();
T Get(int id);
void Add(T item);
void Update(T item);
void Delete(int id);
}
}
DevTest.cs
namespace MonitDbTable.Models
{
public class DevTest
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string CompanyName { get; set; }
[DataType(DataType.Date)]
public DateTime? Date { get; set; }
public int? Clicks { get; set; }
public int? Conversions { get; set; }
public int? Impressions { get; set; }
public string AffiliateName { get; set; }
}
}
DevTestRepository.cs
namespace MonitDbTable.Repositories
{
public class DevTestRepository : IRepository<DevTest>
{
private readonly string _connString = ConfigurationManager.ConnectionStrings["DbConnection"].ConnectionString;
private DevTestContext db;
public DevTestRepository(DevTestContext db)
{
this.db = db;
}
public void Add(DevTest item)
{
db.DevTests.Add(item);
}
public void Delete(int id)
{
var item = db.DevTests.Find(id);
db.DevTests.Remove(item);
}
public DevTest Get(int id)
{
return db.DevTests.Find(id);
}
public IEnumerable<DevTest> GetAll()
{
var devTests = new List<DevTest>();
using (var connection = new SqlConnection(_connString))
{
connection.Open();
using (var command = new SqlCommand(@"SELECT [Id], [CompanyName], [Date], [Clicks], [Conversions], [Impressions], [AffiliateName] FROM [dbo].[DevTests]", connection))
{
command.Notification = null;
var dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
var reader = command.ExecuteReader();
while (reader.Read())
{
devTests.Add(item: new DevTest
{
Id = (int)reader["Id"],
CompanyName = reader["CompanyName"] != DBNull.Value ? (string)reader["CompanyName"] : "",
Date = reader["Date"] != DBNull.Value ? Convert.ToDateTime(reader["Date"]) : (DateTime?)null,
Clicks = reader["Clicks"] != DBNull.Value ? (int)reader["Clicks"] : 0,
Conversions = reader["Conversions"] != DBNull.Value ? (int)reader["Conversions"] : 0,
Impressions = reader["Impressions"] != DBNull.Value ? (int)reader["Impressions"] : 0,
AffiliateName = reader["AffiliateName"] != DBNull.Value ? (string)reader["AffiliateName"] : ""
});
}
}
}
return devTests;
}
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
DevTestsHub.SendMessages();
}
}
public void Update(DevTest item)
{
db.Entry<DevTest>(item).State = System.Data.Entity.EntityState.Modified;
}
}
}
UnitOfWork.cs
namespace MonitDbTable.Repositories
{
public class UnitOfWork : IDisposable
{
private DevTestContext db = new DevTestContext();
private DevTestRepository dtRepository;
public DevTestRepository DevTests
{
get
{
if (dtRepository == null)
dtRepository = new DevTestRepository(db);
return dtRepository;
}
}
public void Save()
{
db.SaveChanges();
}
private bool disposed = false;
public virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
db.Dispose();
}
this.disposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
Интервьюер поставил мне два плюса (2+) и 4- по этому заданию. И один из минусов гласит:
Didn't use interface for unit of work
Собственно именно по этому "минусу" я и хочу чтобы вы меня проконсультировали и помогли разобраться в том как правильно использовать UoW.
IUnitOfWork
или
автор имел ввиду в класс UnitOfWork
внедрить зависимость от
репозитория DevTestRepository
?IUnitOfWork UnitOfWork { get; }
в качестве свойства у interface IRepository<T>
.Но одно я исправил - внедрил зависимость от контекста:
public UnitOfWork(DevTestContext db)
{
this.db = db;
}
Иначе "не возможно" было тестировать WebApi-методы
, которые обращаются к БД через UoW
.
GitHub-ссылка на проект
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Здравствуйте, уважаемыеС помощью ответов из предыдущего вопроса я немного усовершенствовал свой код
В примере показано как работает код, но нужно чтобы ответ приходил не следующей командой, а продолжением запроса