Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Binary file not shown.
Empty file.
Binary file added .vs/APIDesafioDotNetCore.DataBase/v17/.suo
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
964 changes: 964 additions & 0 deletions .vs/APIDesafioDotNetCore/config/applicationhost.config

Large diffs are not rendered by default.

Binary file added .vs/APIDesafioDotNetCore/v17/.futdcache.v2
Binary file not shown.
Binary file added .vs/APIDesafioDotNetCore/v17/.suo
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="7.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.2" />
</ItemGroup>

</Project>
30 changes: 30 additions & 0 deletions API/APIDesafioDotNetCore.DataBase/Context.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using APIDesafioDotNetCore.BancoDeDados.Entidades;
using APIDesafioDotNetCore.BancoDeDados.Entities;
using APIDesafioDotNetCore.BancoDeDados.Mappings;
using APIDesafioDotNetCore.DataBase;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;

namespace APIDesafioDotNetCore.BancoDeDados
{
/// <summary>
/// Data base context implementation
/// </summary>
public sealed class Context : ContextBase
{

/// <summary>
/// Init a <see cref="Context"/> object
/// </summary>
/// <param name="configuration">Configuration file object</param>
public Context(IConfiguration configuration)
: base(configuration)
{
}

/// <inheritdoc />
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseSqlServer(ConnectionString).UseLazyLoadingProxies();

}
}
68 changes: 68 additions & 0 deletions API/APIDesafioDotNetCore.DataBase/ContextBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using APIDesafioDotNetCore.BancoDeDados.Entidades;
using APIDesafioDotNetCore.BancoDeDados.Entities;
using APIDesafioDotNetCore.BancoDeDados.Mappings;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace APIDesafioDotNetCore.DataBase
{
public abstract class ContextBase : DbContext, IContextBase
{
public DbSet<Product> Products { get; set; }

public string ConnectionString { get; }

protected virtual Action<ModelBuilder> DataInitialize { get; }

public ContextBase(string connectionString)
{
ConnectionString = connectionString;
}

public ContextBase(IConfiguration configuration)
: this(configuration["ConnectionString"])
{
}

/// <inheritdoc />
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new ProductMapping());
DataInitialize?.Invoke(modelBuilder);
}

/// <inheritdoc />
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken)
{
AddTimestamps();

return await base.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
}

/// <inheritdoc />
public async Task<int> Push(CancellationToken cancellationToken)
=> await SaveChangesAsync(cancellationToken).ConfigureAwait(false);

private void AddTimestamps()
{
var entities = ChangeTracker.Entries()
.Where(x => x.State == EntityState.Added || x.State == EntityState.Modified);

foreach (var entity in entities)
{
var now = DateTime.Now;

if (entity.State == EntityState.Added)
{
((EntityBase)entity.Entity).CreatedAt = now;
}
((EntityBase)entity.Entity).UpdatedAt = now;
}
}
}
}
29 changes: 29 additions & 0 deletions API/APIDesafioDotNetCore.DataBase/Entities/EntityBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace APIDesafioDotNetCore.BancoDeDados.Entities
{
/// <summary>
/// Entity base class
/// </summary>
public abstract class EntityBase
{
/// <summary>
/// Init a <see cref="EntityBase"/> object
/// </summary>
/// <param name="createdAt">Object criation date</param>
/// <param name="updatedAt">Object update date</param>
public EntityBase(DateTime createdAt, DateTime updatedAt)
{
CreatedAt = createdAt;
UpdatedAt = updatedAt;
}

/// <summary>
/// Object criation date
/// </summary>
public DateTime CreatedAt { get; set; }

/// <summary>
/// Object update date
/// </summary>
public DateTime UpdatedAt { get; set; }
}
}
58 changes: 58 additions & 0 deletions API/APIDesafioDotNetCore.DataBase/Entities/Product.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using APIDesafioDotNetCore.BancoDeDados.Entities;

namespace APIDesafioDotNetCore.BancoDeDados.Entidades
{
/// <summary>
/// Product entity
/// </summary>
public class Product : EntityBase
{
/// <summary>
/// Init a <see cref="Product"/> object
/// </summary>
/// <param name="createdAt">Product criation date</param>
/// <param name="name">Product name</param>
/// <param name="price">Product price</param>
/// <param name="brand">Product brand</param>
/// <param name="updatedAt">Product update date</param>
/// <param name="id">Product ID</param>
public Product(DateTime createdAt, string name, decimal price, string brand, DateTime updatedAt, int id)
: base(createdAt, updatedAt)
{
Name = name;
Price = price;
Brand = brand;
Id = id;
}

public Product(string name, decimal price, string brand)
: base(new DateTime(), new DateTime())
{
Name = name;
Price = price;
Brand = brand;
}



/// <summary>
/// Product name
/// </summary>
public string Name { get; set; }

/// <summary>
/// Product price
/// </summary>
public decimal Price { get; set; }

/// <summary>
/// Product brand
/// </summary>
public string Brand { get; set; }

/// <summary>
/// Product ID
/// </summary>
public int Id { get; set; }
}
}
23 changes: 23 additions & 0 deletions API/APIDesafioDotNetCore.DataBase/IContextBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using APIDesafioDotNetCore.BancoDeDados.Entidades;
using Microsoft.EntityFrameworkCore;

namespace APIDesafioDotNetCore.DataBase
{
/// <summary>
/// Database context definition
/// </summary>
public interface IContextBase
{
/// <summary>
/// Products entity
/// </summary>
DbSet<Product> Products { get; }

/// <summary>
/// Push all changes to database
/// </summary>
/// <param name="cancellationToken">Cancellation token to notify the execution cancellation</param>
/// <returns>Task to async push execution</returns>
Task<int> Push(CancellationToken cancellationToken);
}
}
22 changes: 22 additions & 0 deletions API/APIDesafioDotNetCore.DataBase/Mappings/ProductMapping.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using APIDesafioDotNetCore.BancoDeDados.Entidades;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace APIDesafioDotNetCore.BancoDeDados.Mappings
{
internal sealed class ProductMapping : IEntityTypeConfiguration<Product>
{

public void Configure(EntityTypeBuilder<Product> builder)
{
builder.ToTable("Products").HasKey(_ => _.Id);

builder.Property(_ => _.CreatedAt).HasColumnName("CreatedAt").IsRequired();
builder.Property(_ => _.Name).HasColumnName("Name").IsRequired().HasMaxLength(255);
builder.Property(_ => _.Price).HasColumnName("Price").IsRequired();
builder.Property(_ => _.Brand).HasColumnName("Brand").IsRequired().HasMaxLength(255);
builder.Property(_ => _.UpdatedAt).HasColumnName("UpdatedAt").IsRequired();
builder.Property(_ => _.Id).HasColumnName("Id").ValueGeneratedOnAdd();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using APIDesafioDotNetCore.BancoDeDados.Entidades;

namespace APIDesafioDotNetCore.DataBase.Repositories
{
/// <summary>
/// Product repository definition
/// </summary>
public interface IProductRepository
{
/// <summary>
/// Get product by ID
/// </summary>
/// <param name="id">Product ID to get</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns></returns>
Task<Product> GetProductById(int id, CancellationToken cancellationToken);

/// <summary>
/// Get last product add.
/// </summary>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns></returns>
Task<Product> GetLastProduct(CancellationToken cancellationToken);

/// <summary>
/// Get all products
/// </summary>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns></returns>
IEnumerable<Product> GetAllProduct();

/// <summary>
/// Add product
/// </summary>
/// <param name="product">Product to add</param>
void Add(Product product);

/// <summary>
/// Add product collection
/// </summary>
/// <param name="products">Products to add</param>
void Add(IEnumerable<Product> products);

/// <summary>
/// Update product
/// </summary>
/// <param name="product">Product to update</param>
void Update(Product product);

/// <summary>
/// Exclude product
/// </summary>
/// <param name="product">Product to exclude</param>
void Exclude(Product product);

/// <summary>
/// Exclude product collection
/// </summary>
/// <param name="entidades">Products to exclude</param>
void Exclude(IEnumerable<Product> entidades);

/// <summary>
/// Push all changes to database
/// </summary>
/// <param name="cancellationToken">Cancellation token to notify the execution cancellation</param>
/// <returns>Task to async push execution</returns>
Task Push(CancellationToken cancellationToken);

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using APIDesafioDotNetCore.BancoDeDados;
using APIDesafioDotNetCore.BancoDeDados.Entidades;
using Microsoft.EntityFrameworkCore;

namespace APIDesafioDotNetCore.DataBase.Repositories
{
/// <summary>
/// Product repository implementation
/// </summary>
public sealed class ProductRepository : IProductRepository
{
private IContextBase _context;

/// <summary>
/// Init a <see cref="ProductRepository"/> object
/// </summary>
/// <param name="context">Database context</param>
public ProductRepository(IContextBase context)
{
_context = context;
}

/// <inheritdoc />
public async Task<Product> GetProductById(int id, CancellationToken cancellationToken)
=> _context.Products.Local.FirstOrDefault(_ => _.Id.Equals(_)) ??
await _context.Products.AsQueryable().FirstOrDefaultAsync(_ => _.Id.Equals(id), cancellationToken).ConfigureAwait(false);

/// <inheritdoc />
public async Task<Product> GetLastProduct(CancellationToken cancellationToken)
=> _context.Products.Local.OrderBy(_=>_.Id).LastOrDefault() ??
await _context.Products.AsQueryable().OrderBy(_ => _.Id).LastOrDefaultAsync(cancellationToken).ConfigureAwait(false);

/// <inheritdoc />
public IEnumerable<Product> GetAllProduct()
=> _context.Products;

/// <inheritdoc />
public void Add(Product product)
=> _context.Products.Add(product);

/// <inheritdoc />
public void Add(IEnumerable<Product> products)
=> _context.Products.AddRange(products.Cast<Product>());

/// <inheritdoc />
public void Update(Product product)
=> _context.Products.Update(product);

/// <inheritdoc />
public void Exclude(Product product)
=> _context.Products.Remove(product);

/// <inheritdoc />
public void Exclude(IEnumerable<Product> entidades)
=> _context.Products.RemoveRange(entidades.Cast<Product>());

/// <inheritdoc />
public async Task Push(CancellationToken cancellationToken)
=> await _context.Push(cancellationToken).ConfigureAwait(false);

}
}
Loading