Skip to content

Commit 2b06e03

Browse files
committed
Add CRUD template
1 parent b922669 commit 2b06e03

17 files changed

+515
-1
lines changed

README.md

+23-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ This repository contains `dotnet new` templates for Virto Commerce Modules.
66
* vc-module-dba-xapi - Creates a new Virto Commerce module with DB Agnostic and XAPI support.
77
* vc-module-dba - Creates a new Virto Commerce module with DB Agnostic support.
88
* vc-module-xapi - Creates a new Virto Commerce module with XAPI support.
9+
* vc-crud - Creates all classes required for CRUD operations.
910

1011
## Getting Started
1112

@@ -40,7 +41,7 @@ where `--ModuleName` is your module name, `--Author` is your name, and `--Compan
4041
* `vc-module-customer-reviews` folder with module solution will be created
4142
* You can pass PlatformVersion attribute to create a new module for specific version of Virto Commerce.
4243

43-
### Parameters description
44+
#### Parameters description
4445

4546
| Options | Description | Type | Required | Default value |
4647
|--------|-------------|------|----------|---------------|
@@ -52,6 +53,27 @@ where `--ModuleName` is your module name, `--Author` is your name, and `--Compan
5253
| --CoreVersion | Virto Commerce Core module version | string | Optional | 3.800.0 |
5354
| --XapiVersion (or -X) | XAPI module version | string | Optional | 3.901.0 |
5455

56+
### How to create a CRUD classes from template
57+
58+
Run the following command:
59+
60+
```powershell
61+
dotnet new vc-crud --EntityName FooBar --CompanyName VirtoCommerce --ModuleName CustomerReviews
62+
```
63+
64+
It will create a folder called `vc-module-customer-reviews` with models, events, and services needed for CRUD operations. The company name and the module name are used to create the namespace for new classes.
65+
66+
> [!NOTE]
67+
> You can simply copy the most of these files into your module, but you will need to merge new DbContext.cs, Repository.cs, and Module.cs files with existing ones.
68+
69+
#### Parameters description
70+
71+
| Options | Description | Type | Required | Default value |
72+
|--------|-------------|------|----------|---------------|
73+
| --CompanyName (or -C) | Your company name| string | Optional | VirtoCommerce |
74+
| --ModuleName (or -M) | Your module name | string | Optional | NewModule |
75+
| --EntityName | New entity name (or -E) | string | Optional | FooBar |
76+
5577
## How to uninstall
5678

5779
Run dotnet to uninstall templates
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"$schema": "http://json.schemastore.org/template",
3+
"author": "VirtoWay",
4+
"classifications": [ "ecommerce", "platform", "virtocommerce", "virto", "commerce", "crud" ],
5+
"identity": "VirtoCommerce3.CRUD",
6+
"name": "Virto Commerce 3.x CRUD Template",
7+
"shortName": "vc-crud",
8+
"tags": {
9+
"language": "C#",
10+
"type": "project"
11+
},
12+
"symbols": {
13+
"CompanyName": {
14+
"type": "parameter",
15+
"dataType": "string",
16+
"description": "Your company name",
17+
"defaultValue": "VirtoCommerce",
18+
"replaces": "{CompanyName}",
19+
"fileRename": "{CompanyName}"
20+
},
21+
"ModuleName": {
22+
"type": "parameter",
23+
"dataType": "string",
24+
"description": "Your module name",
25+
"defaultValue": "NewModule",
26+
"replaces": "{ModuleName}",
27+
"fileRename": "{ModuleName}"
28+
},
29+
"EntityName": {
30+
"type": "parameter",
31+
"dataType": "string",
32+
"description": "Your model name",
33+
"defaultValue": "FooBar",
34+
"replaces": "{EntityName}",
35+
"fileRename": "{EntityName}"
36+
},
37+
"KebabModuleName": {
38+
"type": "derived",
39+
"valueSource": "ModuleName",
40+
"valueTransform": "kebab",
41+
"replaces": "{KebabModuleName}",
42+
"fileRename": "{KebabModuleName}"
43+
},
44+
"KebabEntityName": {
45+
"type": "derived",
46+
"valueSource": "EntityName",
47+
"valueTransform": "kebab",
48+
"replaces": "{KebabEntityName}",
49+
"fileRename": "{KebabEntityName}"
50+
},
51+
"joinedNamespace": {
52+
"type": "generated",
53+
"generator": "join",
54+
"parameters": {
55+
"symbols": [
56+
{
57+
"type": "ref",
58+
"value": "CompanyName"
59+
},
60+
{
61+
"type": "ref",
62+
"value": "ModuleName"
63+
}
64+
],
65+
"separator": "."
66+
},
67+
"fileRename": "{Namespace}",
68+
"replaces": "{Namespace}"
69+
}
70+
},
71+
"forms": {
72+
"kebab": {
73+
"identifier": "kebabCase"
74+
}
75+
}
76+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Collections.Generic;
2+
using VirtoCommerce.Platform.Core.Events;
3+
using {Namespace}.Core.Models;
4+
5+
namespace {Namespace}.Core.Events;
6+
7+
public class {EntityName}ChangedEvent : GenericChangedEntryEvent<{EntityName}>
8+
{
9+
public {EntityName}ChangedEvent(IEnumerable<GenericChangedEntry<{EntityName}>> changedEntries)
10+
: base(changedEntries)
11+
{
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Collections.Generic;
2+
using VirtoCommerce.Platform.Core.Events;
3+
using {Namespace}.Core.Models;
4+
5+
namespace {Namespace}.Core.Events;
6+
7+
public class {EntityName}ChangingEvent : GenericChangedEntryEvent<{EntityName}>
8+
{
9+
public {EntityName}ChangingEvent(IEnumerable<GenericChangedEntry<{EntityName}>> changedEntries)
10+
: base(changedEntries)
11+
{
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
using VirtoCommerce.Platform.Core.Common;
3+
4+
namespace {Namespace}.Core.Models;
5+
6+
public class {EntityName} : AuditableEntity, ICloneable
7+
{
8+
public object Clone()
9+
{
10+
return MemberwiseClone();
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
using VirtoCommerce.Platform.Core.Common;
2+
3+
namespace {Namespace}.Core.Models;
4+
5+
public class {EntityName}SearchCriteria : SearchCriteriaBase
6+
{
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
using VirtoCommerce.Platform.Core.Common;
2+
3+
namespace {Namespace}.Core.Models;
4+
5+
public class {EntityName}SearchResult : GenericSearchResult<{EntityName}>
6+
{
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using VirtoCommerce.Platform.Core.GenericCrud;
2+
using {Namespace}.Core.Models;
3+
4+
namespace {Namespace}.Core.Services;
5+
6+
public interface I{EntityName}SearchService : ISearchService<{EntityName}SearchCriteria, {EntityName}SearchResult, {EntityName}>
7+
{
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using VirtoCommerce.Platform.Core.GenericCrud;
2+
using {Namespace}.Core.Models;
3+
4+
namespace {Namespace}.Core.Services;
5+
6+
public interface I{EntityName}Service : ICrudService<{EntityName}>
7+
{
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using VirtoCommerce.Platform.Core.Common;
2+
using VirtoCommerce.Platform.Core.Domain;
3+
using {Namespace}.Core.Models;
4+
5+
namespace {Namespace}.Data.Models;
6+
7+
public class {EntityName}Entity : AuditableEntity, IDataEntity<{EntityName}Entity, {EntityName}>
8+
{
9+
public virtual {EntityName} ToModel({EntityName} model)
10+
{
11+
model.Id = Id;
12+
model.CreatedBy = CreatedBy;
13+
model.CreatedDate = CreatedDate;
14+
model.ModifiedBy = ModifiedBy;
15+
model.ModifiedDate = ModifiedDate;
16+
17+
return model;
18+
}
19+
20+
public virtual {EntityName}Entity FromModel({EntityName} model, PrimaryKeyResolvingMap pkMap)
21+
{
22+
pkMap.AddPair(model, this);
23+
24+
Id = model.Id;
25+
CreatedBy = model.CreatedBy;
26+
CreatedDate = model.CreatedDate;
27+
ModifiedBy = model.ModifiedBy;
28+
ModifiedDate = model.ModifiedDate;
29+
30+
return this;
31+
}
32+
33+
public virtual void Patch({EntityName}Entity target)
34+
{
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Threading.Tasks;
4+
using VirtoCommerce.Platform.Core.Common;
5+
using {Namespace}.Data.Models;
6+
7+
namespace {Namespace}.Data.Repositories;
8+
9+
public interface I{ModuleName}Repository : IRepository
10+
{
11+
IQueryable<{EntityName}Entity> {EntityName}s { get; }
12+
13+
Task<IList<{EntityName}Entity>> Get{EntityName}sByIdsAsync(IList<string> ids, string responseGroup);
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.Reflection;
2+
using Microsoft.EntityFrameworkCore;
3+
using VirtoCommerce.Platform.Data.Infrastructure;
4+
using {Namespace}.Data.Models;
5+
6+
namespace {Namespace}.Data.Repositories;
7+
8+
public class {ModuleName}DbContext : DbContextBase
9+
{
10+
public {ModuleName}DbContext(DbContextOptions<{ModuleName}DbContext> options)
11+
: base(options)
12+
{
13+
}
14+
15+
protected {ModuleName}DbContext(DbContextOptions options)
16+
: base(options)
17+
{
18+
}
19+
20+
protected override void OnModelCreating(ModelBuilder modelBuilder)
21+
{
22+
base.OnModelCreating(modelBuilder);
23+
24+
modelBuilder.Entity<{EntityName}Entity>().ToTable("{EntityName}").HasKey(x => x.Id);
25+
modelBuilder.Entity<{EntityName}Entity>().Property(x => x.Id).HasMaxLength(IdLength).ValueGeneratedOnAdd();
26+
27+
switch (Database.ProviderName)
28+
{
29+
case "Pomelo.EntityFrameworkCore.MySql":
30+
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.Load("{Namespace}.Data.MySql"));
31+
break;
32+
case "Npgsql.EntityFrameworkCore.PostgreSQL":
33+
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.Load("{Namespace}.Data.PostgreSql"));
34+
break;
35+
case "Microsoft.EntityFrameworkCore.SqlServer":
36+
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.Load("{Namespace}.Data.SqlServer"));
37+
break;
38+
}
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Threading.Tasks;
4+
using Microsoft.EntityFrameworkCore;
5+
using VirtoCommerce.Platform.Core.Common;
6+
using VirtoCommerce.Platform.Core.Domain;
7+
using VirtoCommerce.Platform.Data.Infrastructure;
8+
using {Namespace}.Data.Models;
9+
10+
namespace {Namespace}.Data.Repositories;
11+
12+
public class {ModuleName}Repository : DbContextRepositoryBase<{ModuleName}DbContext>, I{ModuleName}Repository
13+
{
14+
public {ModuleName}Repository({ModuleName}DbContext dbContext, IUnitOfWork unitOfWork = null)
15+
: base(dbContext, unitOfWork)
16+
{
17+
}
18+
19+
public IQueryable<{EntityName}Entity> {EntityName}s => DbContext.Set<{EntityName}Entity>();
20+
21+
public virtual async Task<IList<{EntityName}Entity>> Get{EntityName}sByIdsAsync(IList<string> ids, string responseGroup)
22+
{
23+
if (ids.IsNullOrEmpty())
24+
{
25+
return [];
26+
}
27+
28+
return ids.Count == 1
29+
? await {EntityName}s.Where(x => x.Id == ids.First()).ToListAsync()
30+
: await {EntityName}s.Where(x => ids.Contains(x.Id)).ToListAsync();
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Microsoft.Extensions.Options;
5+
using VirtoCommerce.Platform.Core.Caching;
6+
using VirtoCommerce.Platform.Core.Common;
7+
using VirtoCommerce.Platform.Core.GenericCrud;
8+
using VirtoCommerce.Platform.Data.GenericCrud;
9+
using {Namespace}.Core.Models;
10+
using {Namespace}.Core.Services;
11+
using {Namespace}.Data.Models;
12+
using {Namespace}.Data.Repositories;
13+
14+
namespace {Namespace}.Data.Services;
15+
16+
public class {EntityName}SearchService : SearchService<{EntityName}SearchCriteria, {EntityName}SearchResult, {EntityName}, {EntityName}Entity>, I{EntityName}SearchService
17+
{
18+
public {EntityName}SearchService(
19+
Func<I{ModuleName}Repository> repositoryFactory,
20+
IPlatformMemoryCache platformMemoryCache,
21+
I{EntityName}Service crudService,
22+
IOptions<CrudOptions> crudOptions)
23+
: base(repositoryFactory, platformMemoryCache, crudService, crudOptions)
24+
{
25+
}
26+
27+
protected override IQueryable<{EntityName}Entity> BuildQuery(IRepository repository, {EntityName}SearchCriteria criteria)
28+
{
29+
var query = ((I{ModuleName}Repository)repository).{EntityName}s;
30+
return query;
31+
}
32+
33+
protected override IList<SortInfo> BuildSortExpression({EntityName}SearchCriteria criteria)
34+
{
35+
var sortInfos = criteria.SortInfos;
36+
37+
if (sortInfos.IsNullOrEmpty())
38+
{
39+
sortInfos =
40+
[
41+
new SortInfo { SortColumn = nameof({EntityName}Entity.CreatedDate), SortDirection = SortDirection.Descending },
42+
new SortInfo { SortColumn = nameof({EntityName}Entity.Id) },
43+
];
44+
}
45+
46+
return sortInfos;
47+
}
48+
}

0 commit comments

Comments
 (0)