Skip to content

Commit

Permalink
Replaced EF MessageManager with Dapper MessageProvider.
Browse files Browse the repository at this point in the history
  • Loading branch information
LemonsLover committed Mar 24, 2024
1 parent 1db22ea commit 4978093
Show file tree
Hide file tree
Showing 20 changed files with 281 additions and 143 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@
using System.Data.SqlClient;

namespace Geesemon.DataAccess.Dapper;
public class DapperConnection
public class DbConnection
{
public readonly string ConnectionString;

public DapperConnection(IConfiguration config)
public DbConnection(IConfiguration config)
{
if (string.IsNullOrWhiteSpace(config.GetValue<string>("ConnectionString")))
throw new ArgumentNullException("Connection string is not provided. Dapper context wasn't created.");
var connectionString = config.GetValue<string>("ConnectionString");

ConnectionString = config.GetValue<string>("ConnectionString");
if (string.IsNullOrWhiteSpace(connectionString))
throw new ArgumentNullException("Connection string is not provided. Dapper context wasn't initialized.");

ConnectionString = connectionString;
}

public IDbConnection Open() => new SqlConnection(ConnectionString);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,41 @@
using Geesemon.DataAccess.Dapper.Providers;
using Dapper;

using Geesemon.DataAccess.Dapper.Providers;
using Geesemon.DataAccess.Dapper.TypeHandlers;
using Geesemon.Model.Common;

using Microsoft.Extensions.DependencyInjection;

namespace Geesemon.DataAccess.Dapper.Extensions;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddDapperServices(this IServiceCollection services)
public static IServiceCollection InitializeDapper(this IServiceCollection services)
{
services.AddSingleton<DapperConnection>();
AddDapperServices(services);
AddProviders(services);
AddSqlMappers();

services.AddProviders();
return services;
}

private static IServiceCollection AddDapperServices(IServiceCollection services)
{
services.AddSingleton<DbConnection>();

return services;
}

private static IServiceCollection AddProviders(this IServiceCollection services)
private static IServiceCollection AddProviders(IServiceCollection services)
{
services.AddSingleton<UserProvider>();

services.AddSingleton<MessageProvider>();

return services;
}

private static void AddSqlMappers()
{
SqlMapper.AddTypeHandler(typeof(string[]), new JsonTypeHandler<string[]>());
SqlMapper.AddTypeHandler(typeof(ForwardedMessage), new JsonTypeHandler<ForwardedMessage>());
}
}
46 changes: 28 additions & 18 deletions Geesemon.DataAccess.Dapper/Providers/BaseProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@
namespace Geesemon.DataAccess.Dapper.Providers;
public class BaseProvider<T> where T : Entity
{
protected readonly DapperConnection dapperConnection;
protected readonly DbConnection dbConnection;

public BaseProvider(DapperConnection dapperConnection)
public BaseProvider(DbConnection dapperConnection)
{
this.dapperConnection = dapperConnection;
this.dbConnection = dapperConnection;
}

public async Task<T> CreateAsync(T entity)
public virtual async Task<T> CreateAsync(T entity)
{
using var connection = dapperConnection.Open();
using var connection = dbConnection.Open();
int rowsEffected = 0;

var tableName = GetTableName();
Expand All @@ -34,25 +34,35 @@ public async Task<T> CreateAsync(T entity)
return rowsEffected > 0 ? entity : throw new Exception($"Failed to create {nameof(T)} entity in database.");
}

public async Task<bool> RemoveAsync(T entity)

public virtual async Task<T> RemoveAsync(T entity)
{
using var connection = dapperConnection.Open();
using var connection = dbConnection.Open();
int rowsEffected = 0;

var tableName = GetTableName();
var keyColumn = GetKeyColumnName();
var keyProperty = GetKeyPropertyName();

var query = $"DELETE FROM {tableName} WHERE {keyColumn} = @{keyProperty}";
var query = $"DELETE FROM {tableName} WHERE {keyColumn} = @{keyColumn}";

rowsEffected = await connection.ExecuteAsync(query, entity);

return rowsEffected > 0 ? true : false;
return entity;
}

public virtual async Task<T> RemoveByIdAsync(Guid id)
{
T? entity = await GetByIdAsync(id);
if (entity == null)
throw new NullReferenceException("This record with given id doesn't exist.");
entity = await RemoveAsync(entity);
return entity;
}

public async Task<IEnumerable<T>> GetAllAsync()
public virtual async Task<IEnumerable<T>> GetAllAsync()
{
using var connection = dapperConnection.Open();
using var connection = dbConnection.Open();
IEnumerable<T> result = null;

var tableName = GetTableName();
Expand All @@ -63,9 +73,9 @@ public async Task<IEnumerable<T>> GetAllAsync()
return result;
}

public async Task<T> GetByIdAsync(Guid Id)
public virtual async Task<T> GetByIdAsync(Guid Id)
{
using var connection = dapperConnection.Open();
using var connection = dbConnection.Open();
IEnumerable<T> result = null;

var tableName = GetTableName();
Expand All @@ -78,12 +88,12 @@ public async Task<T> GetByIdAsync(Guid Id)
return result.FirstOrDefault();
}

public async Task<IEnumerable<T>> GetByIdsAsync(Guid[] Ids)
public virtual async Task<IEnumerable<T>> GetByIdsAsync(Guid[] Ids)
{
if (Ids.Length == 0)
return Enumerable.Empty<T>();

using var connection = dapperConnection.Open();
using var connection = dbConnection.Open();
IEnumerable<T> result = null;

var tableName = GetTableName();
Expand All @@ -98,14 +108,14 @@ public async Task<IEnumerable<T>> GetByIdsAsync(Guid[] Ids)
return result;
}

public Task<IEnumerable<T>> GetByIdsAsync(IEnumerable<Guid> Ids)
public virtual Task<IEnumerable<T>> GetByIdsAsync(IEnumerable<Guid> Ids)
{
return GetByIdsAsync(Ids.ToArray());
}

public async Task<T> UpdateAsync(T entity)
public virtual async Task<T> UpdateAsync(T entity)
{
using var connection = dapperConnection.Open();
using var connection = dbConnection.Open();
int rowsEffected = 0;

var tableName = GetTableName();
Expand Down
50 changes: 50 additions & 0 deletions Geesemon.DataAccess.Dapper/Providers/MessageProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using Dapper;

using Geesemon.Model.Models;

namespace Geesemon.DataAccess.Dapper.Providers;

public class MessageProvider : BaseProvider<Message>
{
public MessageProvider(DbConnection dbConnection)
: base(dbConnection)
{
}

public async Task<int> GetNotReadMessagesCount(Guid chatId, Guid currentUserId)
{
using var connection = dbConnection.Open();

var tableName = GetTableName();
var query =
$@"
SELECT count(*) FROM {tableName}
WHERE ChatId = @chatId AND
FromId != @currentUserId AND
Messages.Id != ALL (SELECT MessageId FROM ReadMessages WHERE ReadById = @currentUserId)
";
var result = await connection.ExecuteScalarAsync<int>(query, new { chatId, currentUserId });

return result;
}

public async Task<List<Message>> GetByChatIdAsync(Guid chatId, int skip, int take = 30)
{
using var connection = dbConnection.Open();

var tableName = GetTableName();
var columns = GetColumns();
var query =
$@"
SELECT {columns} FROM {tableName}
WHERE(ChatId = @chatId)
ORDER BY CreatedAt desc
OFFSET @skip ROWS
FETCH NEXT @take ROWS ONLY;
";

var response = await connection.QueryAsync<Message>(query, new { take, skip, chatId });

return response.ToList();
}
}
16 changes: 8 additions & 8 deletions Geesemon.DataAccess.Dapper/Providers/UserProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
namespace Geesemon.DataAccess.Dapper.Providers;
public class UserProvider : BaseProvider<User>
{
public UserProvider(DapperConnection dapperConnection)
: base(dapperConnection)
public UserProvider(DbConnection dbConnection)
: base(dbConnection)
{ }

public async Task<List<User>> GetAsync(int take, int skip, string searchQuery, Guid? currentUserId = null)
{
using var connection = dapperConnection.Open();
using var connection = dbConnection.Open();

var tableName = GetTableName();
var query =
Expand All @@ -28,7 +28,7 @@ OFFSET @skip ROWS

public async Task<User?> GetByIdentifierAsync(string identifier)
{
using var connection = dapperConnection.Open();
using var connection = dbConnection.Open();

var tableName = GetTableName();
var query = $"SELECT * FROM {tableName} WHERE Identifier = @identifier";
Expand All @@ -38,7 +38,7 @@ OFFSET @skip ROWS

public async Task<User?> GetByEmailAsync(string email)
{
using var connection = dapperConnection.Open();
using var connection = dbConnection.Open();

var tableName = GetTableName();
var query = $"SELECT * FROM {tableName} WHERE Email = @email";
Expand All @@ -48,7 +48,7 @@ OFFSET @skip ROWS

public async Task<List<User>> GetReadByAsync(Guid messageId, int skip, int take)
{
using var connection = dapperConnection.Open();
using var connection = dbConnection.Open();

var tableName = GetTableName();
var columns = GetColumns();
Expand All @@ -68,7 +68,7 @@ OFFSET @skip ROWS

public async Task<int> GetReadByCountByAsync(Guid messageId)
{
using var connection = dapperConnection.Open();
using var connection = dbConnection.Open();

var tableName = GetTableName();
var query =
Expand All @@ -84,7 +84,7 @@ INNER JOIN {tableName}

public async Task<List<User>> GetAsync(Guid chatId)
{
using var connection = dapperConnection.Open();
using var connection = dbConnection.Open();

var tableName = GetTableName();
var columns = GetColumns();
Expand Down
20 changes: 20 additions & 0 deletions Geesemon.DataAccess.Dapper/TypeHandlers/JsonTypeHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Data;
using System.Text.Json;

using static Dapper.SqlMapper;

namespace Geesemon.DataAccess.Dapper.TypeHandlers;
internal class JsonTypeHandler<T> : TypeHandler<T>
{
public override T? Parse(object value)
{
var json = value.ToString();

return JsonSerializer.Deserialize<T>(json);
}

public override void SetValue(IDbDataParameter parameter, T? value)
{
parameter.Value = JsonSerializer.Serialize(value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ public static IServiceCollection AddMsSql(this IServiceCollection services, stri
});

services.AddScoped<ChatManager>();
services.AddScoped<MessageManager>();
services.AddScoped<UserChatManager>();
services.AddScoped<SessionManager>();
services.AddScoped<ReadMessagesManager>();
Expand Down
22 changes: 11 additions & 11 deletions Geesemon.DataAccess/Managers/MessageManager.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using Geesemon.DataAccess.Providers.MessageProvider;
using Geesemon.Model.Models;
//using Geesemon.DataAccess.Providers.MessageProvider;
//using Geesemon.Model.Models;

namespace Geesemon.DataAccess.Managers
{
public class MessageManager : MessageProvider, IManager<Message>
{
public MessageManager(AppDbContext appContext)
: base(appContext)
{ }
}
}
//namespace Geesemon.DataAccess.Managers
//{
// public class MessageManager : MessageProvider, IManager<Message>
// {
// public MessageManager(AppDbContext appContext)
// : base(appContext)
// { }
// }
//}
Loading

0 comments on commit 4978093

Please sign in to comment.