Skip to content

Commit 36a7628

Browse files
authoredApr 24, 2021
Merge pull request #198 from AntonioFalcao/release
v3.4
2 parents 332834c + ace9856 commit 36a7628

File tree

32 files changed

+271
-250
lines changed

32 files changed

+271
-250
lines changed
 

‎CONTRIBUTING.md

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Contributing
2+
3+
When contributing to this repository, please first discuss the change you wish to make via issue,
4+
email, or any other method with the owners of this repository before making a change.
5+
6+
Please note we have a code of conduct, please follow it in all your interactions with the project.
7+
8+
## Pull Request Process
9+
10+
1. Ensure any install or build dependencies are removed before the end of the layer when doing a
11+
build.
12+
2. Update the README.md with details of changes to the interface, this includes new environment
13+
variables, exposed ports, useful file locations and container parameters.
14+
3. Increase the version numbers in any examples files and the README.md to the new version that this
15+
Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
16+
4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you
17+
do not have permission to do that, you may request the second reviewer to merge it for you.
18+
19+
## Code of Conduct
20+
21+
### Our Pledge
22+
23+
In the interest of fostering an open and welcoming environment, we as
24+
contributors and maintainers pledge to making participation in our project and
25+
our community a harassment-free experience for everyone, regardless of age, body
26+
size, disability, ethnicity, gender identity and expression, level of experience,
27+
nationality, personal appearance, race, religion, or sexual identity and
28+
orientation.
29+
30+
### Our Standards
31+
32+
Examples of behavior that contributes to creating a positive environment
33+
include:
34+
35+
* Using welcoming and inclusive language
36+
* Being respectful of differing viewpoints and experiences
37+
* Gracefully accepting constructive criticism
38+
* Focusing on what is best for the community
39+
* Showing empathy towards other community members
40+
41+
Examples of unacceptable behavior by participants include:
42+
43+
* The use of sexualized language or imagery and unwelcome sexual attention or
44+
advances
45+
* Trolling, insulting/derogatory comments, and personal or political attacks
46+
* Public or private harassment
47+
* Publishing others' private information, such as a physical or electronic
48+
address, without explicit permission
49+
* Other conduct which could reasonably be considered inappropriate in a
50+
professional setting
51+
52+
### Our Responsibilities
53+
54+
Project maintainers are responsible for clarifying the standards of acceptable
55+
behavior and are expected to take appropriate and fair corrective action in
56+
response to any instances of unacceptable behavior.
57+
58+
Project maintainers have the right and responsibility to remove, edit, or
59+
reject comments, commits, code, wiki edits, issues, and other contributions
60+
that are not aligned to this Code of Conduct, or to ban temporarily or
61+
permanently any contributor for other behaviors that they deem inappropriate,
62+
threatening, offensive, or harmful.
63+
64+
### Scope
65+
66+
This Code of Conduct applies both within project spaces and in public spaces
67+
when an individual is representing the project or its community. Examples of
68+
representing a project or community include using an official project e-mail
69+
address, posting via an official social media account, or acting as an appointed
70+
representative at an online or offline event. Representation of a project may be
71+
further defined and clarified by project maintainers.
72+
73+
### Enforcement
74+
75+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
76+
reported by contacting the project team at arfj@edu.univali.br. All
77+
complaints will be reviewed and investigated and will result in a response that
78+
is deemed necessary and appropriate to the circumstances. The project team is
79+
obligated to maintain confidentiality with regard to the reporter of an incident.
80+
Further details of specific enforcement policies may be posted separately.
81+
82+
Project maintainers who do not follow or enforce the Code of Conduct in good
83+
faith may face temporary or permanent repercussions as determined by other
84+
members of the project's leadership.
85+
86+
### Attribution
87+
88+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
89+
available at [http://contributor-covenant.org/version/1/4][version]
90+
91+
[homepage]: http://contributor-covenant.org
92+
[version]: http://contributor-covenant.org/version/1/4/

‎Directory.Build.props

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
<!--GraphQL-->
1919
<GraphQL_Server_Version>5.0.1</GraphQL_Server_Version>
2020
<GraphQL_Client_Version>3.2.3</GraphQL_Client_Version>
21-
<GraphQL_Version>4.2.0</GraphQL_Version>
21+
<GraphQL_Version>4.3.0</GraphQL_Version>
2222

2323
<!--AutoMapper-->
2424
<AutoMapper_DependencyInjection_Version>8.1.1</AutoMapper_DependencyInjection_Version>
@@ -31,7 +31,7 @@
3131
<HealthChecks_Version>5.0.1</HealthChecks_Version>
3232

3333
<!--Others-->
34-
<FluentValidation_Version>10.0.2</FluentValidation_Version>
34+
<FluentValidation_Version>10.0.4</FluentValidation_Version>
3535
<Scrutor_Version>3.3.0</Scrutor_Version>
3636

3737
</PropertyGroup>

‎README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,7 @@ ___
744744

745745
## Contributing
746746

747-
Available soon!
747+
All contributions are welcome. Please take a look at [contributing](./CONTRIBUTING.md) guide.
748748

749749
## Versioning
750750

Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
using Dotnet6.GraphQL4.Domain.Abstractions.Entities;
1+
using System;
2+
using Dotnet6.GraphQL4.Domain.Abstractions.Builders.Extensions;
3+
using Dotnet6.GraphQL4.Domain.Abstractions.Entities;
24

35
namespace Dotnet6.GraphQL4.Domain.Abstractions.Builders
46
{
5-
public abstract class Builder<TBuilder, TEntity, TId> : IBuilder<TEntity, TId>
7+
public abstract class Builder<TBuilder, TEntity, TId> : IBuilder<TBuilder, TEntity, TId>
68
where TBuilder : Builder<TBuilder, TEntity, TId>
79
where TEntity : Entity<TId>
810
where TId : struct
911
{
1012
protected TId Id;
11-
1213
public abstract TEntity Build();
1314

14-
public TBuilder WithId(TId id)
15-
{
16-
Id = id;
17-
return (TBuilder) this;
18-
}
15+
public TBuilder With<TProperty>(Func<TBuilder, TProperty> func)
16+
=> ((TBuilder) this).With<TBuilder, TProperty>(func);
1917
}
2018
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
3+
namespace Dotnet6.GraphQL4.Domain.Abstractions.Builders.Extensions
4+
{
5+
internal static class BuilderExtensions
6+
{
7+
internal static TBuilder With<TBuilder, TProperty>(this TBuilder builder, Func<TBuilder, TProperty> func)
8+
{
9+
func(builder);
10+
return builder;
11+
}
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
using Dotnet6.GraphQL4.Domain.Abstractions.Entities;
1+
using System;
2+
using Dotnet6.GraphQL4.Domain.Abstractions.Entities;
23

34
namespace Dotnet6.GraphQL4.Domain.Abstractions.Builders
45
{
5-
public interface IBuilder<out TEntity, TId>
6+
public interface IBuilder<out TBuilder, out TEntity, TId>
7+
where TBuilder : IBuilder<TBuilder, TEntity, TId>
68
where TEntity : Entity<TId>
79
where TId : struct
810
{
911
TEntity Build();
12+
TBuilder With<TProperty>(Func<TBuilder, TProperty> func);
1013
}
1114
}

‎src/Dotnet6.GraphQL4.Domain.Abstractions/DependencyInjection/Extensions/ServiceCollectionExtensions.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public static class ServiceCollectionExtensions
1010
public static IServiceCollection AddBuilders(this IServiceCollection services)
1111
=> services
1212
.Scan(selector => selector.FromAssemblies(Application.Assemblies)
13-
.AddClasses(filter => filter.AssignableTo(typeof(IBuilder<,>)))
13+
.AddClasses(filter => filter.AssignableTo(typeof(IBuilder<,,>)))
1414
.UsingRegistrationStrategy(RegistrationStrategy.Skip)
1515
.AsImplementedInterfaces()
1616
.WithScopedLifetime());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
4+
namespace Dotnet6.GraphQL4.Domain.Abstractions.ValueObjects
5+
{
6+
public abstract class ValueObject
7+
{
8+
protected static bool EqualOperator(ValueObject left, ValueObject right)
9+
=> (ReferenceEquals(left, null) ^ ReferenceEquals(right, null)) is false &&
10+
(ReferenceEquals(left, null) || left.Equals(right));
11+
12+
protected static bool NotEqualOperator(ValueObject left, ValueObject right)
13+
=> EqualOperator(left, right) is false;
14+
15+
protected abstract IEnumerable<object> GetEqualityComponents();
16+
17+
public override bool Equals(object obj)
18+
=> obj is not null && obj.GetType() == GetType() &&
19+
GetEqualityComponents().SequenceEqual(((ValueObject) obj).GetEqualityComponents());
20+
21+
public override int GetHashCode()
22+
=> GetEqualityComponents()
23+
.Select(x => x != null ? x.GetHashCode() : 0)
24+
.Aggregate((x, y) => x ^ y);
25+
}
26+
}

‎src/Dotnet6.GraphQL4.Repositories.Abstractions/Transactions/TransactionScopeExecutor.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ public TransactionScopeExecutor<T> WithConditionAsync(Func<CancellationToken, Ta
5858
return this;
5959
}
6060

61+
public T Execute()
62+
=> Execute(_operation);
63+
64+
public Task<T> ExecuteAsync(CancellationToken cancellationToken)
65+
=> ExecuteAsync(_operationAsync, cancellationToken);
66+
6167
public T Execute(Func<T> operation)
6268
{
6369
using var scope = CreateScope();
@@ -66,12 +72,6 @@ public T Execute(Func<T> operation)
6672
return result;
6773
}
6874

69-
public T Execute()
70-
=> Execute(_operation);
71-
72-
public Task<T> ExecuteAsync(CancellationToken cancellationToken)
73-
=> ExecuteAsync(_operationAsync, cancellationToken);
74-
7575
public async Task<T> ExecuteAsync(Func<CancellationToken, Task<T>> operationAsync, CancellationToken cancellationToken)
7676
{
7777
using var scope = CreateScope();

‎src/Dotnet6.GraphQL4.Repositories.Abstractions/UnitsOfWork/IUnitOfWork.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ namespace Dotnet6.GraphQL4.Repositories.Abstractions.UnitsOfWork
66
{
77
public interface IUnitOfWork
88
{
9-
TResult ExecuteInTransaction<TResult>(Func<TResult> operation, Func<bool> condition);
10-
Task<TResult> ExecuteInTransactionAsync<TResult>(Func<CancellationToken, Task<TResult>> operationAsync, Func<CancellationToken, Task<bool>> condition, CancellationToken cancellationToken);
9+
TResult ExecuteInTransactionScope<TResult>(Func<TResult> operation, Func<bool> condition);
10+
Task<TResult> ExecuteInTransactionScopeAsync<TResult>(Func<CancellationToken, Task<TResult>> operationAsync, Func<CancellationToken, Task<bool>> condition, CancellationToken cancellationToken);
1111

1212
bool SaveChanges();
1313
Task<bool> SaveChangesAsync(CancellationToken cancellationToken);
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Threading;
33
using System.Threading.Tasks;
4-
using System.Transactions;
54
using Dotnet6.GraphQL4.CrossCutting.Notifications;
65
using Dotnet6.GraphQL4.Repositories.Abstractions.DependencyInjection.Options;
76
using Dotnet6.GraphQL4.Repositories.Abstractions.Transactions.Extensions;
@@ -21,46 +20,46 @@ public class UnitOfWork : IUnitOfWork
2120

2221
public UnitOfWork(
2322
DbContext dbContext,
24-
IOptionsMonitor<ApplicationTransactionOptions> optionsMonitor,
23+
IOptionsSnapshot<ApplicationTransactionOptions> optionsMonitor,
2524
INotificationContext notificationContext)
2625
{
2726
_dbContext = dbContext;
28-
_options = optionsMonitor.CurrentValue;
27+
_options = optionsMonitor.Value;
2928
_database = _dbContext.Database;
3029
_notificationContext = notificationContext;
3130
}
3231

33-
public TResult ExecuteInTransaction<TResult>(Func<TResult> operation, Func<bool> condition)
34-
=> CreateExecutionStrategy().Execute(() => ExecuteWithScope(operation, condition));
32+
public TResult ExecuteInTransactionScope<TResult>(Func<TResult> operation, Func<bool> condition)
33+
=> CreateExecutionStrategy().Execute(() => ExecuteInScope(operation, condition));
3534

36-
public Task<TResult> ExecuteInTransactionAsync<TResult>(Func<CancellationToken, Task<TResult>> operationAsync, Func<CancellationToken, Task<bool>> condition, CancellationToken cancellationToken)
37-
=> CreateExecutionStrategy().ExecuteAsync(ct => ExecuteWithScopeAsync(operationAsync, condition, ct), cancellationToken);
35+
public Task<TResult> ExecuteInTransactionScopeAsync<TResult>(Func<CancellationToken, Task<TResult>> operationAsync, Func<CancellationToken, Task<bool>> condition, CancellationToken cancellationToken)
36+
=> CreateExecutionStrategy().ExecuteAsync(ct => ExecuteInScopeAsync(operationAsync, condition, ct), cancellationToken);
3837

39-
private Task<TResult> ExecuteWithScopeAsync<TResult>(Func<CancellationToken, Task<TResult>> operationAsync, Func<CancellationToken, Task<bool>> condition, CancellationToken cancellationToken)
38+
private Task<TResult> ExecuteInScopeAsync<TResult>(Func<CancellationToken, Task<TResult>> operationAsync, Func<CancellationToken, Task<bool>> condition, CancellationToken cancellationToken)
4039
=> operationAsync
4140
.BeginTransactionScope()
42-
.WithScopeOption(TransactionScopeOption.Required)
41+
.WithScopeOption()
4342
.WithOptions(options => options.IsolationLevel = _options.IsolationLevel)
44-
.WithScopeAsyncFlowOption(TransactionScopeAsyncFlowOption.Enabled)
43+
.WithScopeAsyncFlowOption()
4544
.WithConditionAsync(condition ?? (_ => _notificationContext.AllValidAsync))
4645
.ExecuteAsync(cancellationToken);
4746

48-
private TResult ExecuteWithScope<TResult>(Func<TResult> operation, Func<bool> condition)
47+
private TResult ExecuteInScope<TResult>(Func<TResult> operation, Func<bool> condition)
4948
=> operation
5049
.BeginTransactionScope()
51-
.WithScopeOption(TransactionScopeOption.Required)
50+
.WithScopeOption()
5251
.WithOptions(options => options.IsolationLevel = _options.IsolationLevel)
53-
.WithScopeAsyncFlowOption(TransactionScopeAsyncFlowOption.Enabled)
52+
.WithScopeAsyncFlowOption()
5453
.WithCondition(condition ?? (() => _notificationContext.AllValid))
5554
.Execute();
5655

5756
private IExecutionStrategy CreateExecutionStrategy()
5857
=> _database.CreateExecutionStrategy();
5958

6059
public bool SaveChanges()
61-
=> _dbContext.SaveChanges(false) > default(int);
60+
=> _dbContext.SaveChanges(false) > 0;
6261

6362
public async Task<bool> SaveChangesAsync(CancellationToken cancellationToken)
64-
=> await _dbContext.SaveChangesAsync(false, cancellationToken) > default(int);
63+
=> await _dbContext.SaveChangesAsync(false, cancellationToken) > 0;
6564
}
6665
}

‎src/Dotnet6.GraphQL4.Store.Domain/Entities/Products/Backpacks/BackpackBuilder.cs

+3-9
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,11 @@
33

44
namespace Dotnet6.GraphQL4.Store.Domain.Entities.Products.Backpacks
55
{
6-
public class BackpackBuilder : ProductBuilder<Backpack, Guid>, IBackpackBuilder
6+
public class BackpackBuilder : ProductBuilder<BackpackBuilder, Backpack, Guid>, IBackpackBuilder
77
{
8-
private BackpackType _type;
8+
public BackpackType Type { get; set; }
99

1010
public override Backpack Build()
11-
=> new(Id, Description, IntroduceAt, Name, PhotoUrl, Price, ProductType, Rating, Stock, Option, _type);
12-
13-
public IBackpackBuilder WithType(BackpackType type)
14-
{
15-
_type = type;
16-
return this;
17-
}
11+
=> new(Id, Description, IntroduceAt, Name, PhotoUrl, Price, ProductType, Rating, Stock, Option, Type);
1812
}
1913
}

‎src/Dotnet6.GraphQL4.Store.Domain/Entities/Products/Backpacks/IBackpackBuilder.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
namespace Dotnet6.GraphQL4.Store.Domain.Entities.Products.Backpacks
55
{
6-
public interface IBackpackBuilder : IProductBuilder<Backpack, Guid>
6+
public interface IBackpackBuilder : IProductBuilder<BackpackBuilder, Backpack, Guid>
77
{
8-
IBackpackBuilder WithType(BackpackType type);
8+
BackpackType Type { get; set; }
99
}
1010
}

‎src/Dotnet6.GraphQL4.Store.Domain/Entities/Products/Boots/BootBuilder.cs

+4-16
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,12 @@
33

44
namespace Dotnet6.GraphQL4.Store.Domain.Entities.Products.Boots
55
{
6-
public class BootBuilder : ProductBuilder<Boot, Guid>, IBootBuilder
6+
public class BootBuilder : ProductBuilder<BootBuilder, Boot, Guid>, IBootBuilder
77
{
8-
private int _size;
9-
private BootType _type;
8+
public BootType Type { get; set; }
9+
public int Size { get; set; }
1010

1111
public override Boot Build()
12-
=> new(Id, Description, IntroduceAt, Name, PhotoUrl, Price, ProductType, Rating, Stock, Option, _type, _size);
13-
14-
public IBootBuilder WithType(BootType type)
15-
{
16-
_type = type;
17-
return this;
18-
}
19-
20-
public IBootBuilder WithSize(int size)
21-
{
22-
_size = size;
23-
return this;
24-
}
12+
=> new(Id, Description, IntroduceAt, Name, PhotoUrl, Price, ProductType, Rating, Stock, Option, Type, Size);
2513
}
2614
}

‎src/Dotnet6.GraphQL4.Store.Domain/Entities/Products/Boots/IBootBuilder.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33

44
namespace Dotnet6.GraphQL4.Store.Domain.Entities.Products.Boots
55
{
6-
public interface IBootBuilder : IProductBuilder<Boot, Guid>
6+
public interface IBootBuilder : IProductBuilder<BootBuilder,Boot, Guid>
77
{
8-
IBootBuilder WithType(BootType type);
9-
IBootBuilder WithSize(int size);
8+
BootType Type { get; set; }
9+
int Size { get; set; }
1010
}
1111
}

‎src/Dotnet6.GraphQL4.Store.Domain/Entities/Products/IProductBuilder.cs

+11-10
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,19 @@
66

77
namespace Dotnet6.GraphQL4.Store.Domain.Entities.Products
88
{
9-
public interface IProductBuilder<out TProduct, TId> : IBuilder<TProduct, TId>
9+
public interface IProductBuilder<out TBuilder, out TProduct, TId> : IBuilder<TBuilder, TProduct, TId>
10+
where TBuilder : IBuilder<TBuilder, TProduct, TId>
1011
where TProduct : Entity<TId>, IProduct
1112
where TId : struct
1213
{
13-
IProductBuilder<TProduct, TId> WithDescription(string description);
14-
IProductBuilder<TProduct, TId> WithIntroduceAt(DateTimeOffset introduceAt);
15-
IProductBuilder<TProduct, TId> WithName(string name);
16-
IProductBuilder<TProduct, TId> WithOption(Option option);
17-
IProductBuilder<TProduct, TId> WithPhotoUrl(string photoUrl);
18-
IProductBuilder<TProduct, TId> WithPrice(decimal price);
19-
IProductBuilder<TProduct, TId> WithProductType(ProductType productType);
20-
IProductBuilder<TProduct, TId> WithRating(int rating);
21-
IProductBuilder<TProduct, TId> WithStock(int stock);
14+
string Description { get; set; }
15+
DateTimeOffset IntroduceAt { get; set; }
16+
string Name { get; set; }
17+
Option Option { get; set; }
18+
string PhotoUrl { get; set; }
19+
decimal Price { get; set; }
20+
ProductType ProductType { get; set; }
21+
int Rating { get; set; }
22+
int Stock { get; set; }
2223
}
2324
}

‎src/Dotnet6.GraphQL4.Store.Domain/Entities/Products/Kayaks/IKayakBuilder.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33

44
namespace Dotnet6.GraphQL4.Store.Domain.Entities.Products.Kayaks
55
{
6-
public interface IKayakBuilder : IProductBuilder<Kayak, Guid>
6+
public interface IKayakBuilder : IProductBuilder<KayakBuilder, Kayak, Guid>
77
{
8-
IKayakBuilder WithAmountOfPerson(int amountOfPerson);
9-
IKayakBuilder WithType(KayakType type);
8+
int AmountOfPerson { get; set; }
9+
KayakType Type { get; set; }
1010
}
1111
}

‎src/Dotnet6.GraphQL4.Store.Domain/Entities/Products/Kayaks/KayakBuilder.cs

+4-16
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,12 @@
33

44
namespace Dotnet6.GraphQL4.Store.Domain.Entities.Products.Kayaks
55
{
6-
public class KayakBuilder : ProductBuilder<Kayak, Guid>, IKayakBuilder
6+
public class KayakBuilder : ProductBuilder<KayakBuilder, Kayak, Guid>, IKayakBuilder
77
{
8-
private int _amountOfPerson;
9-
private KayakType _type;
10-
11-
public IKayakBuilder WithAmountOfPerson(int amountOfPerson)
12-
{
13-
_amountOfPerson = amountOfPerson;
14-
return this;
15-
}
16-
17-
public IKayakBuilder WithType(KayakType type)
18-
{
19-
_type = type;
20-
return this;
21-
}
8+
public int AmountOfPerson { get; set; }
9+
public KayakType Type { get; set; }
2210

2311
public override Kayak Build()
24-
=> new(Id, Description, IntroduceAt, Name, PhotoUrl, Price, ProductType, Rating, Stock, Option, _type, _amountOfPerson);
12+
=> new(Id, Description, IntroduceAt, Name, PhotoUrl, Price, ProductType, Rating, Stock, Option, Type, AmountOfPerson);
2513
}
2614
}

‎src/Dotnet6.GraphQL4.Store.Domain/Entities/Products/ProductBuilder.cs

+11-64
Original file line numberDiff line numberDiff line change
@@ -6,72 +6,19 @@
66

77
namespace Dotnet6.GraphQL4.Store.Domain.Entities.Products
88
{
9-
public abstract class ProductBuilder<TProduct, TId> : Builder<ProductBuilder<TProduct, TId>, TProduct, TId>, IProductBuilder<TProduct, TId>
9+
public abstract class ProductBuilder<TProductBuilder, TProduct, TId> : Builder<TProductBuilder, TProduct, TId>, IProductBuilder<TProductBuilder, TProduct, TId>
10+
where TProductBuilder : ProductBuilder<TProductBuilder, TProduct, TId>
1011
where TProduct : Entity<TId>, IProduct
1112
where TId : struct
1213
{
13-
protected string Description;
14-
protected DateTimeOffset IntroduceAt;
15-
protected string Name;
16-
protected Option Option;
17-
protected string PhotoUrl;
18-
protected decimal Price;
19-
protected ProductType ProductType;
20-
protected int Rating;
21-
protected int Stock;
22-
23-
public IProductBuilder<TProduct, TId> WithDescription(string description)
24-
{
25-
Description = description;
26-
return this;
27-
}
28-
29-
public IProductBuilder<TProduct, TId> WithIntroduceAt(DateTimeOffset introduceAt)
30-
{
31-
IntroduceAt = introduceAt;
32-
return this;
33-
}
34-
35-
public IProductBuilder<TProduct, TId> WithName(string name)
36-
{
37-
Name = name;
38-
return this;
39-
}
40-
41-
public IProductBuilder<TProduct, TId> WithOption(Option option)
42-
{
43-
Option = option;
44-
return this;
45-
}
46-
47-
public IProductBuilder<TProduct, TId> WithPhotoUrl(string photoUrl)
48-
{
49-
PhotoUrl = photoUrl;
50-
return this;
51-
}
52-
53-
public IProductBuilder<TProduct, TId> WithPrice(decimal price)
54-
{
55-
Price = price;
56-
return this;
57-
}
58-
59-
public IProductBuilder<TProduct, TId> WithProductType(ProductType productType)
60-
{
61-
ProductType = productType;
62-
return this;
63-
}
64-
65-
public IProductBuilder<TProduct, TId> WithRating(int rating)
66-
{
67-
Rating = rating;
68-
return this;
69-
}
70-
71-
public IProductBuilder<TProduct, TId> WithStock(int stock)
72-
{
73-
Stock = stock;
74-
return this;
75-
}
14+
public string Description { get; set; }
15+
public DateTimeOffset IntroduceAt { get; set; }
16+
public string Name { get; set; }
17+
public Option Option { get; set; }
18+
public string PhotoUrl { get; set; }
19+
public decimal Price { get; set; }
20+
public ProductType ProductType { get; set; }
21+
public int Rating { get; set; }
22+
public int Stock { get; set; }
7623
}
7724
}

‎src/Dotnet6.GraphQL4.Store.Domain/Entities/Reviews/IReviewBuilder.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33

44
namespace Dotnet6.GraphQL4.Store.Domain.Entities.Reviews
55
{
6-
public interface IReviewBuilder : IBuilder<Review, Guid>
6+
public interface IReviewBuilder : IBuilder<ReviewBuilder, Review, Guid>
77
{
8-
IReviewBuilder WithTitle(string title);
9-
IReviewBuilder WithComment(string comment);
10-
IReviewBuilder WithProductReference(Guid productId);
8+
string Title { get; set; }
9+
string Comment { get; set; }
10+
Guid ProductId { get; set; }
1111
}
1212
}

‎src/Dotnet6.GraphQL4.Store.Domain/Entities/Reviews/ReviewBuilder.cs

+5-22
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,11 @@ namespace Dotnet6.GraphQL4.Store.Domain.Entities.Reviews
55
{
66
public class ReviewBuilder : Builder<ReviewBuilder, Review, Guid>, IReviewBuilder
77
{
8-
private string _comment;
9-
private Guid _productId;
10-
private string _title;
8+
public string Title { get; set; }
9+
public string Comment { get; set; }
10+
public Guid ProductId { get; set; }
1111

12-
public override Review Build() => new(_title, _comment, _productId);
13-
14-
public IReviewBuilder WithTitle(string title)
15-
{
16-
_title = title;
17-
return this;
18-
}
19-
20-
public IReviewBuilder WithComment(string comment)
21-
{
22-
_comment = comment;
23-
return this;
24-
}
25-
26-
public IReviewBuilder WithProductReference(Guid productId)
27-
{
28-
_productId = productId;
29-
return this;
30-
}
12+
public override Review Build()
13+
=> new(Title, Comment, ProductId);
3114
}
3215
}

‎src/Dotnet6.GraphQL4.Store.Repositories/Configurations/Products/ProductConfiguration.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ public void Configure(EntityTypeBuilder<Product> builder)
6060
builder
6161
.HasDiscriminator()
6262
.HasValue<Boot>(nameof(Boot))
63-
?.HasValue<Kayak>(nameof(Kayak))
64-
?.HasValue<Backpack>(nameof(Backpack));
63+
.HasValue<Kayak>(nameof(Kayak))
64+
.HasValue<Backpack>(nameof(Backpack));
6565

6666
builder
6767
.Property(DiscriminatorDefaultName)

‎src/Dotnet6.GraphQL4.Store.Repositories/Contexts/StoreDbContext.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ public StoreDbContext(
2121
DbContextOptions options,
2222
ILoggerFactory loggerFactory,
2323
IConfiguration configuration,
24-
IOptionsMonitor<SqlServerRetryingOptions> optionsMonitor)
24+
IOptionsSnapshot<SqlServerRetryingOptions> optionsMonitor)
2525
: base(options)
2626
{
2727
_loggerFactory = loggerFactory;
2828
_configuration = configuration;
29-
_options = optionsMonitor.CurrentValue;
29+
_options = optionsMonitor.Value;
3030
}
3131

3232
public DbSet<Product> Products { get; set; }
@@ -45,7 +45,8 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
4545
{
4646
if (optionsBuilder.IsConfigured) return;
4747

48-
optionsBuilder.EnableDetailedErrors()
48+
optionsBuilder
49+
.EnableDetailedErrors()
4950
.EnableSensitiveDataLogging()
5051
.UseSqlServer(
5152
connectionString:_configuration.GetConnectionString("DefaultConnection"),

‎src/Dotnet6.GraphQL4.Store.Services/ProductService.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public Task<Review> AddReviewAsync(ReviewModel reviewModel, CancellationToken ca
3030
return default;
3131
}
3232

33-
return UnitOfWork.ExecuteInTransactionAsync(
33+
return UnitOfWork.ExecuteInTransactionScopeAsync(
3434
operationAsync: async ct =>
3535
{
3636
var product = await Repository.GetByIdAsync(

‎src/Dotnet6.GraphQL4.Store.Services/Profiles/Converters/BackpackModelToDomainConverter.cs

+9-9
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ public BackpackModelToDomainConverter(IBackpackBuilder builder)
1515

1616
public Backpack Convert(BackpackModel source, Backpack destination, ResolutionContext context)
1717
=> _builder
18-
.WithType(source.Type)
19-
.WithDescription(source.Description)
20-
.WithName(source.Name)
21-
.WithPrice(source.Price)
22-
.WithRating(source.Rating)
23-
.WithStock(source.Stock)
24-
.WithIntroduceAt(source.IntroduceAt)
25-
.WithPhotoUrl(source.PhotoUrl)
26-
.WithProductType(source.ProductType)
18+
.With(builder => builder.Type = source.Type)
19+
.With(builder => builder.Description = source.Description)
20+
.With(builder => builder.Name = source.Name)
21+
.With(builder => builder.Price = source.Price)
22+
.With(builder => builder.Rating = source.Rating)
23+
.With(builder => builder.Stock = source.Stock)
24+
.With(builder => builder.IntroduceAt = source.IntroduceAt)
25+
.With(builder => builder.PhotoUrl = source.PhotoUrl)
26+
.With(builder => builder.ProductType = source.ProductType)
2727
.Build();
2828
}
2929
}

‎src/Dotnet6.GraphQL4.Store.Services/Profiles/Converters/BootModelToDomainConverter.cs

+10-10
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ public BootModelToDomainConverter(IBootBuilder builder)
1515

1616
public Boot Convert(BootModel source, Boot destination, ResolutionContext context)
1717
=> _builder
18-
.WithType(source.Type)
19-
.WithSize(source.Size)
20-
.WithDescription(source.Description)
21-
.WithName(source.Name)
22-
.WithPrice(source.Price)
23-
.WithRating(source.Rating)
24-
.WithStock(source.Stock)
25-
.WithIntroduceAt(source.IntroduceAt)
26-
.WithPhotoUrl(source.PhotoUrl)
27-
.WithProductType(source.ProductType)
18+
.With(builder => builder.Type = source.Type)
19+
.With(builder => builder.Size = source.Size)
20+
.With(builder => builder.Description = source.Description)
21+
.With(builder => builder.Name = source.Name)
22+
.With(builder => builder.Price = source.Price)
23+
.With(builder => builder.Rating = source.Rating)
24+
.With(builder => builder.Stock = source.Stock)
25+
.With(builder => builder.IntroduceAt = source.IntroduceAt)
26+
.With(builder => builder.PhotoUrl = source.PhotoUrl)
27+
.With(builder => builder.ProductType = source.ProductType)
2828
.Build();
2929
}
3030
}

‎src/Dotnet6.GraphQL4.Store.Services/Profiles/Converters/KayakModelToDomainConverter.cs

+10-10
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ public KayakModelToDomainConverter(IKayakBuilder builder)
1515

1616
public Kayak Convert(KayakModel source, Kayak destination, ResolutionContext context)
1717
=> _builder
18-
.WithType(source.Type)
19-
.WithAmountOfPerson(source.AmountOfPerson)
20-
.WithDescription(source.Description)
21-
.WithName(source.Name)
22-
.WithPrice(source.Price)
23-
.WithRating(source.Rating)
24-
.WithStock(source.Stock)
25-
.WithIntroduceAt(source.IntroduceAt)
26-
.WithPhotoUrl(source.PhotoUrl)
27-
.WithProductType(source.ProductType)
18+
.With(builder => builder.Type = source.Type)
19+
.With(builder => builder.AmountOfPerson = source.AmountOfPerson)
20+
.With(builder => builder.Description = source.Description)
21+
.With(builder => builder.Name = source.Name)
22+
.With(builder => builder.Price = source.Price)
23+
.With(builder => builder.Rating = source.Rating)
24+
.With(builder => builder.Stock = source.Stock)
25+
.With(builder => builder.IntroduceAt = source.IntroduceAt)
26+
.With(builder => builder.PhotoUrl = source.PhotoUrl)
27+
.With(builder => builder.ProductType = source.ProductType)
2828
.Build();
2929
}
3030
}

‎src/Dotnet6.GraphQL4.Store.Services/Profiles/Converters/ReviewModelToDomainConverter.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ public ReviewModelToDomainConverter(IReviewBuilder builder)
1515

1616
public Review Convert(ReviewModel source, Review destination, ResolutionContext context)
1717
=> _builder
18-
.WithComment(source.Comment)
19-
.WithTitle(source.Title)
20-
.WithProductReference(source.ProductId)
18+
.With(builder => builder.Comment = source.Comment)
19+
.With(builder => builder.Title = source.Title)
20+
.With(builder => builder.ProductId = source.ProductId)
2121
.Build();
2222
}
2323
}

‎src/Dotnet6.GraphQL4.Store.WebAPI/DependencyInjection/Extensions/ExceptionHandlerExtensions.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public static IApplicationBuilder UseApplicationExceptionHandler(this IApplicati
1515
{
1616
var exception = httpContext.Features.Get<IExceptionHandlerFeature>()?.Error;
1717

18-
Log.Logger.Error("[Exception Handler] {Error}", exception?.Message);
18+
Log.Error("[Exception Handler] {Error}", exception?.Message);
1919

2020
await httpContext.Response.WriteAsJsonAsync(
2121
value: new ExecutionResult().AddError(new(exception?.Message)),
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,27 @@
1-
using System;
2-
using System.Text.Json;
1+
using System.Text.Json;
32
using System.Text.Json.Serialization;
43
using Dotnet6.GraphQL4.Store.WebAPI.Graphs;
54
using Dotnet6.GraphQL4.Store.WebAPI.Graphs.Executers;
65
using GraphQL;
76
using GraphQL.Server;
7+
using Microsoft.AspNetCore.Hosting;
88
using Microsoft.Extensions.DependencyInjection;
9+
using Microsoft.Extensions.Hosting;
910
using Serilog;
1011

1112
namespace Dotnet6.GraphQL4.Store.WebAPI.DependencyInjection.Extensions
1213
{
1314
public static class ServiceCollectionExtensions
1415
{
15-
private static readonly Options Options = new();
16-
17-
public static IGraphQLBuilder AddApplicationGraphQL(this IServiceCollection services, Action<Options> actionOptions)
18-
{
19-
actionOptions(Options);
20-
21-
return services
16+
public static IGraphQLBuilder AddApplicationGraphQL(this IServiceCollection services)
17+
=> services
2218
.AddScoped(typeof(IGraphQLExecuter<>), typeof(StoreGraphQLExecuter<>))
2319
.AddScoped<IDocumentExecuter, StoreDocumentExecuter>()
2420
.AddSingleton<StoreSchema>()
2521
.AddGraphQL(
26-
(options, _) =>
22+
(options, serviceProvider) =>
2723
{
28-
options.EnableMetrics = Options.IsDevelopment;
24+
options.EnableMetrics = serviceProvider.GetRequiredService<IWebHostEnvironment>().IsDevelopment();
2925

3026
options.UnhandledExceptionDelegate = exceptionContext
3127
=> Log.Error(
@@ -44,11 +40,5 @@ public static IGraphQLBuilder AddApplicationGraphQL(this IServiceCollection serv
4440
.AddWebSockets()
4541
.AddDataLoader()
4642
.AddGraphTypes(typeof(StoreSchema));
47-
}
48-
}
49-
50-
public class Options
51-
{
52-
public bool IsDevelopment { get; set; }
5343
}
5444
}

‎src/Dotnet6.GraphQL4.Store.WebAPI/Startup.cs

+5-7
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ public void Configure(IApplicationBuilder app , ILoggerFactory loggerFactory)
8282

8383
public void ConfigureServices(IServiceCollection services)
8484
{
85+
services.ConfigureTransactionOptions(_configuration.GetSection("Transactions"));
86+
services.ConfigureSqlServerRetryingOptions(_configuration.GetSection("SqlServerRetryingOptions"));
87+
8588
services
8689
.AddLogging()
8790
.AddBuilders()
@@ -92,15 +95,10 @@ public void ConfigureServices(IServiceCollection services)
9295
.AddApplicationMessageServices()
9396
.AddApplicationSubjects()
9497
.AddApplicationAutoMapper()
98+
.AddApplicationDbContext()
9599
.AddControllers();
96100

97-
services.ConfigureTransactionOptions(_configuration.GetSection("Transactions"));
98-
services.ConfigureSqlServerRetryingOptions(_configuration.GetSection("SqlServerRetryingOptions"));
99-
100-
services.AddApplicationDbContext();
101-
102-
services.AddApplicationGraphQL(options
103-
=> options.IsDevelopment = _env.IsDevelopment());
101+
services.AddApplicationGraphQL();
104102

105103
services.Configure<KestrelServerOptions>(options
106104
=> options.AllowSynchronousIO = true);

‎src/Dotnet6.GraphQL4.Store.WebAPI/appsettings.Development.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"MinimumLevel": {
1818
"Default": "Debug",
1919
"Override": {
20-
"Microsoft": "Warning",
20+
"Microsoft": "Information",
2121
"Microsoft.Hosting.Lifetime": "Information"
2222
}
2323
}

0 commit comments

Comments
 (0)
Please sign in to comment.