Skip to content

Commit

Permalink
Merge pull request #26 from tigernetframework/max
Browse files Browse the repository at this point in the history
#7 Created initial data access layer
  • Loading branch information
dotnetgoo committed Apr 4, 2023
2 parents b54328d + e3acd46 commit b93f47f
Show file tree
Hide file tree
Showing 34 changed files with 1,458 additions and 51 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -360,4 +360,7 @@ MigrationBackup/
.ionide/

# Fody - auto-generated XML schema
FodyWeavers.xsd
FodyWeavers.xsd

# For JetBrains IDE files
*.idea
11 changes: 0 additions & 11 deletions Tigernet.Samples.RestApi/Abstractions/IUserClever.cs

This file was deleted.

9 changes: 9 additions & 0 deletions Tigernet.Samples.RestApi/Clevers/Interfaces/IUserClever.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Tigernet.Hosting.DataAccess.Clevers;
using Tigernet.Samples.RestApi.Models;

namespace Tigernet.Samples.RestApi.Clevers.Interfaces;

public interface IUserClever : ICleverBase<User, int>
{
User Add(User user);
}
59 changes: 42 additions & 17 deletions Tigernet.Samples.RestApi/Clevers/UserClever.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,53 @@
using Tigernet.Samples.RestApi.Abstractions;
using Tigernet.Hosting.DataAccess.Clevers;
using Tigernet.Samples.RestApi.Clevers.Interfaces;
using Tigernet.Samples.RestApi.Models;

namespace Tigernet.Samples.RestApi.Clevers
{
public class UserClever : IUserClever
public class UserClever : CleverBase<User, int>, IUserClever
{
private List<User> users = new List<User>
private static List<User> users = new List<User>
{
new User { Id = 1, Name = "Mukhammadkarim", Age = 12 },
new User { Id = 2, Name = "Samandar", Age = 32 },
new User { Id = 3, Name = "Djakhongir", Age = 35 },
new User { Id = 4, Name = "Ixtiyor", Age = 56 },
new User { Id = 5, Name = "Yunusjon", Age = 34 },
new User { Id = 6, Name = "Sabohat", Age = 23 },
new User
{
Id = 1,
Name = "Mukhammadkarim",
Age = 12
},
new User
{
Id = 2,
Name = "Samandar",
Age = 32
},
new User
{
Id = 3,
Name = "Djakhongir",
Age = 35
},
new User
{
Id = 4,
Name = "Ixtiyor",
Age = 56
},
new User
{
Id = 5,
Name = "Yunusjon",
Age = 34
},
new User
{
Id = 6,
Name = "Sabohat",
Age = 23
},
};

public User Get(int id)
public UserClever() : base(users.AsQueryable())
{
return GetAll().FirstOrDefault(p => p.Id == id);
}

public IEnumerable<User> GetAll()
{
return users;
}

public User Add(User user)
Expand All @@ -32,4 +57,4 @@ public User Add(User user)
return user;
}
}
}
}
12 changes: 9 additions & 3 deletions Tigernet.Samples.RestApi/Models/User.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
namespace Tigernet.Samples.RestApi.Models
using Tigernet.Hosting.Attributes.Query;
using Tigernet.Hosting.Models.Common;

namespace Tigernet.Samples.RestApi.Models
{
public class User
public class User : IEntity<int>, IQueryableEntity
{
public int Id { get; set; }

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

public int Age { get; set; }
}
}
}
2 changes: 1 addition & 1 deletion Tigernet.Samples.RestApi/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Tigernet.Hosting;
using Tigernet.Samples.RestApi.Abstractions;
using Tigernet.Samples.RestApi.Clevers;
using Tigernet.Samples.RestApi.Clevers.Interfaces;

var builder = new TigernetHostBuilder("http://localhost:5000/");

Expand Down
19 changes: 10 additions & 9 deletions Tigernet.Samples.RestApi/Resters/UsersRester.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using Tigernet.Hosting.Actions;
using Tigernet.Hosting.Attributes.HttpMethods;
using Tigernet.Hosting.Attributes.Resters;
using Tigernet.Samples.RestApi.Abstractions;
using Tigernet.Hosting.Models.Query;
using Tigernet.Samples.RestApi.Clevers.Interfaces;
using Tigernet.Samples.RestApi.Models;

namespace Tigernet.Samples.RestApi.Resters
{
[ApiRester]
Expand All @@ -15,17 +17,17 @@ public UsersRester(IUserClever userClever)
this.userClever = userClever;
}


[Getter("/all")]
public object GetAll()
[Poster("/by-filter")]
public async ValueTask<object> GetByFilter(EntityQueryOptions<User> model)
{
return Ok(userClever.GetAll());
return Ok(await userClever.GetAsync(model));
}

[Getter]
public object Get()
public async ValueTask<object> Get()
{
return Ok(userClever.Get(1));
var result = await userClever.GetByIdAsync(1);
return Ok(result);
}

[Poster("/new")]
Expand All @@ -36,10 +38,9 @@ public object Add()
Id = 7,
Name = "Ikrom",
Age = 28

};

return Ok(userClever.Add(user));
}
}
}
}
2 changes: 1 addition & 1 deletion src/Tigernet.Hosting/Actions/ResterBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ public object Ok(object data)
return JsonSerializer.Serialize(data);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Tigernet.Hosting.Attributes.Commons;
namespace Tigernet.Hosting.Attributes.HttpMethods.Commons;

/// <summary>
/// Identifies an action that supports a given set of HTTP methods.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Tigernet.Hosting.Attributes.Commons;
using Tigernet.Hosting.Attributes.HttpMethods.Commons;

namespace Tigernet.Hosting.Attributes.HttpMethods;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Tigernet.Hosting.Attributes.Commons;
using Tigernet.Hosting.Attributes.HttpMethods.Commons;

namespace Tigernet.Hosting.Attributes.HttpMethods;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Tigernet.Hosting.Attributes.Query
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class SearchablePropertyAttribute : Attribute
{
}
}
64 changes: 64 additions & 0 deletions src/Tigernet.Hosting/DataAccess/Clevers/CleverBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System.Linq.Expressions;
using Tigernet.Hosting.Extensions;
using Tigernet.Hosting.Models.Common;
using Tigernet.Hosting.Models.Query;

namespace Tigernet.Hosting.DataAccess.Clevers;

/// <summary>
/// Provides base clever implementation
/// </summary>
/// <typeparam name="TEntity">Data type</typeparam>
/// <typeparam name="TKey">Data Id type</typeparam>
public class CleverBase<TEntity, TKey> : ICleverBase<TEntity, TKey> where TEntity : class, IEntity<TKey>, IQueryableEntity where TKey : struct
{
public IQueryable<TEntity> DataSource { init; get; }

public CleverBase()
{
DataSource = Enumerable.Empty<TEntity>().AsQueryable();
}

public CleverBase(IQueryable<TEntity> dataSource)
{
DataSource = dataSource;
}

public virtual IQueryable<TEntity> Get(Expression<Func<TEntity, bool>> expression)
{
return DataSource.Where(expression);
}

public virtual ValueTask<IEnumerable<TEntity>> GetAsync(
Expression<Func<TEntity, bool>> expression,
CancellationToken cancellationToken = default
)
{
if (expression is null)
throw new ArgumentException("Query expression cannot be null");

return new ValueTask<IEnumerable<TEntity>>(DataSource.Where(expression).ToList());
}

public virtual ValueTask<IEnumerable<TEntity>> GetAsync(IEntityQueryOptions<TEntity> queryOptions, CancellationToken cancellationToken = default)
{
if (queryOptions is null)
throw new ArgumentException("Query options cannot be null");

return new ValueTask<IEnumerable<TEntity>>(DataSource.Where(x => true).ApplyQuery(queryOptions).ToList());
}

public virtual ValueTask<TEntity?> GetFirstAsync(IEntityQueryOptions<TEntity> queryOptions, CancellationToken cancellationToken = default)
{
if (queryOptions is null)
throw new ArgumentException("Query options cannot be null");

queryOptions.AddPagination(1, 1);
return new ValueTask<TEntity?>(DataSource.Where(x => true).ApplyQuery(queryOptions).FirstOrDefault());
}

public virtual ValueTask<TEntity?> GetByIdAsync(TKey id, CancellationToken cancellationToken = default)
{
return new ValueTask<TEntity?>(Task.FromResult(DataSource.FirstOrDefault(x => x.Id.Equals(id))));
}
}
50 changes: 50 additions & 0 deletions src/Tigernet.Hosting/DataAccess/Clevers/ICleverBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System.Linq.Expressions;
using Tigernet.Hosting.Models.Common;
using Tigernet.Hosting.Models.Query;

namespace Tigernet.Hosting.DataAccess.Clevers;

/// <summary>
/// Defines base clever interface
/// </summary>
public interface ICleverBase<TEntity, TKey> where TEntity : class, IEntity<TKey>, IQueryableEntity where TKey : struct
{
/// <summary>
/// Gets entity set as queryable collection without decryption
/// </summary>
/// <param name="expression">Predicate expression</param>
/// <returns>Queryable collection of entity</returns>
IQueryable<TEntity> Get(Expression<Func<TEntity, bool>> expression);

/// <summary>
/// Gets entity set after querying
/// </summary>
/// <param name="expression">Predicate expression</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Set of entities</returns>
ValueTask<IEnumerable<TEntity>> GetAsync(Expression<Func<TEntity, bool>> expression, CancellationToken cancellationToken = default);

/// <summary>
/// Gets a set of entities by filter
/// </summary>
/// <param name="queryOptions">Complex query options</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Set of entities after query</returns>
ValueTask<IEnumerable<TEntity>> GetAsync(IEntityQueryOptions<TEntity> queryOptions, CancellationToken cancellationToken = default);

/// <summary>
/// Gets a set of entities by filter
/// </summary>
/// <param name="queryOptions">Complex query options</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Set of entities after query</returns>
ValueTask<TEntity?> GetFirstAsync(IEntityQueryOptions<TEntity> queryOptions, CancellationToken cancellationToken = default);

/// <summary>
/// Gets entity by Id
/// </summary>
/// <param name="id">Id of entity</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Entity if found, otherwise null</returns>
ValueTask<TEntity?> GetByIdAsync(TKey id, CancellationToken cancellationToken = default);
}
40 changes: 40 additions & 0 deletions src/Tigernet.Hosting/Extensions/EntityExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Tigernet.Hosting.Models.Common;

namespace Tigernet.Hosting.Extensions;

/// <summary>
/// Provides extensions specifically for entities
/// </summary>
public static class EntityExtensions
{
/// <summary>
/// Checks whether given type is entity
/// </summary>
/// <param name="type">Type to check</param>
/// <returns>True if given type is entity, otherwise false</returns>
/// <returns><see langword="true" /> if given type is entity; <see langword="false" /> otherwise.</returns>
private static bool IsEntity(this Type type)
{
return type.InheritsOrImplements(typeof(IQueryableEntity));
}

/// <summary>
/// Gets direct child entities from a type
/// </summary>
/// <param name="type">Type to get direct child entities</param>
/// <returns>Set of direct child entities</returns>
/// <exception cref="ArgumentException">If type is null</exception>
public static IEnumerable<Type> GetDirectChildEntities(this Type type)
{
if (type == null)
throw new ArgumentException("Cannot get direct children for null type");

if (!type.IsEntity())
return Enumerable.Empty<Type>();

// Get children
var result = type.GetProperties().Where(x => x.PropertyType.IsClass && x.PropertyType.IsEntity()).Select(x => x.PropertyType).ToList();

return result.Distinct();
}
}
Loading

0 comments on commit b93f47f

Please sign in to comment.