diff --git a/angular/src/app/app-routing.module.ts b/angular/src/app/app-routing.module.ts
index db325cc..0c10118 100644
--- a/angular/src/app/app-routing.module.ts
+++ b/angular/src/app/app-routing.module.ts
@@ -28,6 +28,7 @@ const routes: Routes = [
{ path: 'books', loadChildren: () => import('./book/book.module').then(m => m.BookModule) },
{ path: 'customer', loadChildren: () => import('./customer/customer.module').then(m => m.CustomerModule) },
{ path: 'book-issue', loadChildren: () => import('./book-issue/book-issue.module').then(m => m.BookIssueModule) },
+ { path: 'authors', loadChildren: () => import('./author/author.module').then(m => m.AuthorModule) },
];
@NgModule({
diff --git a/angular/src/app/author/author-routing.module.ts b/angular/src/app/author/author-routing.module.ts
new file mode 100644
index 0000000..d98b5e1
--- /dev/null
+++ b/angular/src/app/author/author-routing.module.ts
@@ -0,0 +1,11 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { AuthorComponent } from './author.component';
+
+const routes: Routes = [{ path: '', component: AuthorComponent }];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class AuthorRoutingModule { }
diff --git a/angular/src/app/author/author.component.html b/angular/src/app/author/author.component.html
new file mode 100644
index 0000000..f10ece7
--- /dev/null
+++ b/angular/src/app/author/author.component.html
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ row.birthDate | date }}
+
+
+
+
+
+
+
+
+ {{ (selectedAuthor.id ? '::Edit' : '::NewAuthor') | abpLocalization }}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/angular/src/app/author/author.component.scss b/angular/src/app/author/author.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/angular/src/app/author/author.component.spec.ts b/angular/src/app/author/author.component.spec.ts
new file mode 100644
index 0000000..de86bad
--- /dev/null
+++ b/angular/src/app/author/author.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AuthorComponent } from './author.component';
+
+describe('AuthorComponent', () => {
+ let component: AuthorComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [AuthorComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(AuthorComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/angular/src/app/author/author.component.ts b/angular/src/app/author/author.component.ts
new file mode 100644
index 0000000..d7fd231
--- /dev/null
+++ b/angular/src/app/author/author.component.ts
@@ -0,0 +1,93 @@
+import { Component, OnInit } from '@angular/core';
+import { ListService, PagedResultDto } from '@abp/ng.core';
+import { AuthorService, AuthorDto } from '@proxy/authors';
+import { FormGroup, FormBuilder, Validators } from '@angular/forms';
+import { NgbDateNativeAdapter, NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap';
+import { ConfirmationService, Confirmation } from '@abp/ng.theme.shared';
+
+@Component({
+ selector: 'app-author',
+ templateUrl: './author.component.html',
+ styleUrls: ['./author.component.scss'],
+ providers: [ListService, { provide: NgbDateAdapter, useClass: NgbDateNativeAdapter }],
+})
+export class AuthorComponent implements OnInit {
+ author = { items: [], totalCount: 0 } as PagedResultDto;
+
+ isModalOpen = false;
+
+ form: FormGroup;
+
+ selectedAuthor = {} as AuthorDto;
+
+ constructor(
+ public readonly list: ListService,
+ private authorService: AuthorService,
+ private fb: FormBuilder,
+ private confirmation: ConfirmationService
+ ) {}
+
+ ngOnInit(): void {
+ const authorStreamCreator = (query) => this.authorService.getList(query);
+
+ this.list.hookToQuery(authorStreamCreator).subscribe((response) => {
+ this.author = response;
+ });
+ }
+
+ createAuthor() {
+ this.selectedAuthor = {} as AuthorDto;
+ this.buildForm();
+ this.isModalOpen = true;
+ }
+
+ editAuthor(id: string) {
+ this.authorService.get(id).subscribe((author) => {
+ this.selectedAuthor = author;
+ this.buildForm();
+ this.isModalOpen = true;
+ });
+ }
+
+ buildForm() {
+ this.form = this.fb.group({
+ name: [this.selectedAuthor.name || '', Validators.required],
+ birthDate: [
+ this.selectedAuthor.birthDate ? new Date(this.selectedAuthor.birthDate) : null,
+ Validators.required,
+ ],
+ shortBio:[this.selectedAuthor.shortBio || '', Validators.required],
+ });
+ }
+
+ save() {
+ if (this.form.invalid) {
+ return;
+ }
+
+ if (this.selectedAuthor.id) {
+ this.authorService
+ .update(this.selectedAuthor.id, this.form.value)
+ .subscribe(() => {
+ this.isModalOpen = false;
+ this.form.reset();
+ this.list.get();
+ });
+ } else {
+ this.authorService.create(this.form.value).subscribe(() => {
+ this.isModalOpen = false;
+ this.form.reset();
+ this.list.get();
+ });
+ }
+ }
+
+ delete(id: string) {
+ this.confirmation.warn('::AreYouSureToDelete', '::AreYouSure')
+ .subscribe((status) => {
+ if (status === Confirmation.Status.confirm) {
+ this.authorService.delete(id).subscribe(() => this.list.get());
+ }
+ });
+ }
+}
diff --git a/angular/src/app/author/author.module.ts b/angular/src/app/author/author.module.ts
new file mode 100644
index 0000000..d97c115
--- /dev/null
+++ b/angular/src/app/author/author.module.ts
@@ -0,0 +1,21 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { AuthorRoutingModule } from './author-routing.module';
+import { AuthorComponent } from './author.component';
+import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap';
+import { SharedModule } from '../shared/shared.module';
+
+
+@NgModule({
+ declarations: [
+ AuthorComponent
+ ],
+ imports: [
+ CommonModule,
+ AuthorRoutingModule,
+ NgbDatepickerModule,
+ SharedModule
+ ]
+})
+export class AuthorModule { }
diff --git a/angular/src/app/book/book.component.html b/angular/src/app/book/book.component.html
index e6536a9..7440674 100644
--- a/angular/src/app/book/book.component.html
+++ b/angular/src/app/book/book.component.html
@@ -63,6 +63,12 @@
{{ row.price | currency }}
+
+
@@ -104,6 +110,16 @@
(click)="datepicker.toggle()"
/>
+
+ *
+
+
+
diff --git a/angular/src/app/book/book.component.ts b/angular/src/app/book/book.component.ts
index 1f543e5..f0df6c9 100644
--- a/angular/src/app/book/book.component.ts
+++ b/angular/src/app/book/book.component.ts
@@ -1,32 +1,41 @@
import { ListService, PagedResultDto } from '@abp/ng.core';
import { Component, OnInit } from '@angular/core';
-import { FormBuilder, FormGroup, Validators } from '@angular/forms';
-import { BookService, BookDto, bookTypeOptions } from '@proxy/books';
+import { BookService, BookDto, bookTypeOptions, AuthorLookupDto } from '@proxy/books';
+import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { NgbDateNativeAdapter, NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap';
import { ConfirmationService, Confirmation } from '@abp/ng.theme.shared';
+import { Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
@Component({
selector: 'app-book',
templateUrl: './book.component.html',
styleUrls: ['./book.component.scss'],
- providers: [ListService,
- { provide: NgbDateAdapter, useClass: NgbDateNativeAdapter } // add this line
- ],
+ providers: [ListService, { provide: NgbDateAdapter, useClass: NgbDateNativeAdapter }],
})
export class BookComponent implements OnInit {
- book = { items: [], totalCount: 0 } as PagedResultDto;
- selectedBook = {} as BookDto; // declare selectedBook
- isModalOpen = false; // add this line
- form: FormGroup; // add this line
+ book = { items: [], totalCount: 0 } as PagedResultDto;
+
+ form: FormGroup;
+
+ selectedBook = {} as BookDto;
+
+ authors$: Observable;
+
bookTypes = bookTypeOptions;
- constructor(public readonly list: ListService, private bookService: BookService, private fb: FormBuilder,
- private confirmation: ConfirmationService
- ) {}
+ isModalOpen = false;
+
+ constructor(
+ public readonly list: ListService,
+ private bookService: BookService,
+ private fb: FormBuilder,
+ private confirmation: ConfirmationService
+ ) {
+ this.authors$ = bookService.getAuthorLookup().pipe(map((r) => r.items));
+ }
ngOnInit() {
- debugger;
-
const bookStreamCreator = (query) => this.bookService.getList(query);
this.list.hookToQuery(bookStreamCreator).subscribe((response) => {
@@ -34,55 +43,54 @@ export class BookComponent implements OnInit {
});
}
-
- // add new method
createBook() {
- this.buildForm(); // add this line
- this.selectedBook = {} as BookDto; // reset the selected book
-
+ this.selectedBook = {} as BookDto;
+ this.buildForm();
this.isModalOpen = true;
}
+
+ editBook(id: string) {
+ this.bookService.get(id).subscribe((book) => {
+ this.selectedBook = book;
+ this.buildForm();
+ this.isModalOpen = true;
+ });
+ }
+
buildForm() {
this.form = this.fb.group({
- name: ['', Validators.required],
- type: [null, Validators.required],
- publishDate: [null, Validators.required],
- price: [null, Validators.required],
+ authorId: [this.selectedBook.authorId || null, Validators.required],
+ name: [this.selectedBook.name || null, Validators.required],
+ type: [this.selectedBook.type || null, Validators.required],
+ publishDate: [
+ this.selectedBook.publishDate ? new Date(this.selectedBook.publishDate) : null,
+ Validators.required,
+ ],
+ price: [this.selectedBook.price || null, Validators.required],
});
}
+
save() {
if (this.form.invalid) {
return;
}
+
const request = this.selectedBook.id
- ? this.bookService.update(this.selectedBook.id, this.form.value)
- : this.bookService.create(this.form.value);
-
- request.subscribe(() => {
- this.isModalOpen = false;
- this.form.reset();
- this.list.get();
- });
- }
+ ? this.bookService.update(this.selectedBook.id, this.form.value)
+ : this.bookService.create(this.form.value);
- // Add editBook method
- editBook(id: string) {
- this.bookService.get(id).subscribe((book) => {
- this.selectedBook = book;
- this.buildForm();
- this.form.controls["name"].setValue(this.selectedBook.name);
- this.form.controls["type"].setValue(this.selectedBook.type);
- this.form.controls["publishDate"].setValue(this.selectedBook.publishDate);
- this.form.controls["price"].setValue(this.selectedBook.price);
- this.isModalOpen = true;
- });
- }
+ request.subscribe(() => {
+ this.isModalOpen = false;
+ this.form.reset();
+ this.list.get();
+ });
+ }
- delete(id: string) {
- this.confirmation.warn('::AreYouSureToDelete', '::AreYouSure').subscribe((status) => {
- if (status === Confirmation.Status.confirm) {
- this.bookService.delete(id).subscribe(() => this.list.get());
- }
- });
- }
+ delete(id: string) {
+ this.confirmation.warn('::AreYouSureToDelete', 'AbpAccount::AreYouSure').subscribe((status) => {
+ if (status === Confirmation.Status.confirm) {
+ this.bookService.delete(id).subscribe(() => this.list.get());
+ }
+ });
+ }
}
diff --git a/angular/src/app/proxy/books/book.service.ts b/angular/src/app/proxy/books/book.service.ts
index 3b0dce7..b9d19ac 100644
--- a/angular/src/app/proxy/books/book.service.ts
+++ b/angular/src/app/proxy/books/book.service.ts
@@ -1,6 +1,6 @@
-import type { BookDto, CreateUpdateBookDto } from './models';
+import type { AuthorLookupDto, BookDto, CreateUpdateBookDto } from './models';
import { RestService, Rest } from '@abp/ng.core';
-import type { PagedAndSortedResultRequestDto, PagedResultDto } from '@abp/ng.core';
+import type { ListResultDto, PagedAndSortedResultRequestDto, PagedResultDto } from '@abp/ng.core';
import { Injectable } from '@angular/core';
@Injectable({
@@ -35,6 +35,14 @@ export class BookService {
{ apiName: this.apiName,...config });
+ getAuthorLookup = (config?: Partial) =>
+ this.restService.request>({
+ method: 'GET',
+ url: '/api/app/book/author-lookup',
+ },
+ { apiName: this.apiName,...config });
+
+
getBookDropDown = (config?: Partial) =>
this.restService.request({
method: 'GET',
diff --git a/angular/src/app/proxy/books/models.ts b/angular/src/app/proxy/books/models.ts
index e61a8e4..ee42a9f 100644
--- a/angular/src/app/proxy/books/models.ts
+++ b/angular/src/app/proxy/books/models.ts
@@ -1,11 +1,17 @@
-import type { AuditedEntityDto } from '@abp/ng.core';
+import type { AuditedEntityDto, EntityDto } from '@abp/ng.core';
import type { BookType } from './book-type.enum';
+export interface AuthorLookupDto extends EntityDto {
+ name?: string;
+}
+
export interface BookDto extends AuditedEntityDto {
name?: string;
type: BookType;
publishDate?: string;
price: number;
+ authorId?: string;
+ authorName?: string;
}
export interface CreateUpdateBookDto {
@@ -13,4 +19,5 @@ export interface CreateUpdateBookDto {
type: BookType;
publishDate: string;
price: number;
+ authorId?: string;
}
diff --git a/angular/src/app/proxy/generate-proxy.json b/angular/src/app/proxy/generate-proxy.json
index 87e4018..3d4a223 100644
--- a/angular/src/app/proxy/generate-proxy.json
+++ b/angular/src/app/proxy/generate-proxy.json
@@ -1530,6 +1530,14 @@
"typeSimple": "[Acme.BookStore.Books.BookDto]"
}
},
+ {
+ "name": "GetAuthorLookupAsync",
+ "parametersOnMethod": [],
+ "returnValue": {
+ "type": "Volo.Abp.Application.Dtos.ListResultDto",
+ "typeSimple": "Volo.Abp.Application.Dtos.ListResultDto"
+ }
+ },
{
"name": "GetAsync",
"parametersOnMethod": [
@@ -1627,6 +1635,119 @@
}
],
"actions": {
+ "GetAsyncById": {
+ "uniqueName": "GetAsyncById",
+ "name": "GetAsync",
+ "httpMethod": "GET",
+ "url": "api/app/book/{id}",
+ "supportedVersions": [],
+ "parametersOnMethod": [
+ {
+ "name": "id",
+ "typeAsString": "System.Guid, System.Private.CoreLib",
+ "type": "System.Guid",
+ "typeSimple": "string",
+ "isOptional": false,
+ "defaultValue": null
+ }
+ ],
+ "parameters": [
+ {
+ "nameOnMethod": "id",
+ "name": "id",
+ "jsonName": null,
+ "type": "System.Guid",
+ "typeSimple": "string",
+ "isOptional": false,
+ "defaultValue": null,
+ "constraintTypes": [],
+ "bindingSourceId": "Path",
+ "descriptorName": ""
+ }
+ ],
+ "returnValue": {
+ "type": "Acme.BookStore.Books.BookDto",
+ "typeSimple": "Acme.BookStore.Books.BookDto"
+ },
+ "allowAnonymous": false,
+ "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService"
+ },
+ "GetListAsyncByInput": {
+ "uniqueName": "GetListAsyncByInput",
+ "name": "GetListAsync",
+ "httpMethod": "GET",
+ "url": "api/app/book",
+ "supportedVersions": [],
+ "parametersOnMethod": [
+ {
+ "name": "input",
+ "typeAsString": "Volo.Abp.Application.Dtos.PagedAndSortedResultRequestDto, Volo.Abp.Ddd.Application.Contracts",
+ "type": "Volo.Abp.Application.Dtos.PagedAndSortedResultRequestDto",
+ "typeSimple": "Volo.Abp.Application.Dtos.PagedAndSortedResultRequestDto",
+ "isOptional": false,
+ "defaultValue": null
+ }
+ ],
+ "parameters": [
+ {
+ "nameOnMethod": "input",
+ "name": "Sorting",
+ "jsonName": null,
+ "type": "System.String",
+ "typeSimple": "string",
+ "isOptional": false,
+ "defaultValue": null,
+ "constraintTypes": null,
+ "bindingSourceId": "ModelBinding",
+ "descriptorName": "input"
+ },
+ {
+ "nameOnMethod": "input",
+ "name": "SkipCount",
+ "jsonName": null,
+ "type": "System.Int32",
+ "typeSimple": "number",
+ "isOptional": false,
+ "defaultValue": null,
+ "constraintTypes": null,
+ "bindingSourceId": "ModelBinding",
+ "descriptorName": "input"
+ },
+ {
+ "nameOnMethod": "input",
+ "name": "MaxResultCount",
+ "jsonName": null,
+ "type": "System.Int32",
+ "typeSimple": "number",
+ "isOptional": false,
+ "defaultValue": null,
+ "constraintTypes": null,
+ "bindingSourceId": "ModelBinding",
+ "descriptorName": "input"
+ }
+ ],
+ "returnValue": {
+ "type": "Volo.Abp.Application.Dtos.PagedResultDto",
+ "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto"
+ },
+ "allowAnonymous": false,
+ "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService"
+ },
+ "GetAuthorLookupAsync": {
+ "uniqueName": "GetAuthorLookupAsync",
+ "name": "GetAuthorLookupAsync",
+ "httpMethod": "GET",
+ "url": "api/app/book/author-lookup",
+ "supportedVersions": [],
+ "parametersOnMethod": [],
+ "parameters": [],
+ "returnValue": {
+ "type": "Volo.Abp.Application.Dtos.ListResultDto",
+ "typeSimple": "Volo.Abp.Application.Dtos.ListResultDto"
+ },
+ "allowAnonymous": false,
+ "implementFrom": "Acme.BookStore.Books.IBookAppService"
+ },
"GetBookDropDown": {
"uniqueName": "GetBookDropDown",
"name": "GetBookDropDown",
@@ -1639,7 +1760,7 @@
"type": "System.Collections.Generic.List",
"typeSimple": "[Acme.BookStore.Books.BookDto]"
},
- "allowAnonymous": null,
+ "allowAnonymous": false,
"implementFrom": "Acme.BookStore.Books.IBookAppService"
},
"CreateAsyncByInput": {
@@ -1676,7 +1797,7 @@
"type": "Acme.BookStore.Books.BookDto",
"typeSimple": "Acme.BookStore.Books.BookDto"
},
- "allowAnonymous": null,
+ "allowAnonymous": false,
"implementFrom": "Volo.Abp.Application.Services.ICreateAppService"
},
"UpdateAsyncByIdAndInput": {
@@ -1733,7 +1854,7 @@
"type": "Acme.BookStore.Books.BookDto",
"typeSimple": "Acme.BookStore.Books.BookDto"
},
- "allowAnonymous": null,
+ "allowAnonymous": false,
"implementFrom": "Volo.Abp.Application.Services.IUpdateAppService"
},
"DeleteAsyncById": {
@@ -1770,106 +1891,8 @@
"type": "System.Void",
"typeSimple": "System.Void"
},
- "allowAnonymous": null,
+ "allowAnonymous": false,
"implementFrom": "Volo.Abp.Application.Services.IDeleteAppService"
- },
- "GetAsyncById": {
- "uniqueName": "GetAsyncById",
- "name": "GetAsync",
- "httpMethod": "GET",
- "url": "api/app/book/{id}",
- "supportedVersions": [],
- "parametersOnMethod": [
- {
- "name": "id",
- "typeAsString": "System.Guid, System.Private.CoreLib",
- "type": "System.Guid",
- "typeSimple": "string",
- "isOptional": false,
- "defaultValue": null
- }
- ],
- "parameters": [
- {
- "nameOnMethod": "id",
- "name": "id",
- "jsonName": null,
- "type": "System.Guid",
- "typeSimple": "string",
- "isOptional": false,
- "defaultValue": null,
- "constraintTypes": [],
- "bindingSourceId": "Path",
- "descriptorName": ""
- }
- ],
- "returnValue": {
- "type": "Acme.BookStore.Books.BookDto",
- "typeSimple": "Acme.BookStore.Books.BookDto"
- },
- "allowAnonymous": null,
- "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService"
- },
- "GetListAsyncByInput": {
- "uniqueName": "GetListAsyncByInput",
- "name": "GetListAsync",
- "httpMethod": "GET",
- "url": "api/app/book",
- "supportedVersions": [],
- "parametersOnMethod": [
- {
- "name": "input",
- "typeAsString": "Volo.Abp.Application.Dtos.PagedAndSortedResultRequestDto, Volo.Abp.Ddd.Application.Contracts",
- "type": "Volo.Abp.Application.Dtos.PagedAndSortedResultRequestDto",
- "typeSimple": "Volo.Abp.Application.Dtos.PagedAndSortedResultRequestDto",
- "isOptional": false,
- "defaultValue": null
- }
- ],
- "parameters": [
- {
- "nameOnMethod": "input",
- "name": "Sorting",
- "jsonName": null,
- "type": "System.String",
- "typeSimple": "string",
- "isOptional": false,
- "defaultValue": null,
- "constraintTypes": null,
- "bindingSourceId": "ModelBinding",
- "descriptorName": "input"
- },
- {
- "nameOnMethod": "input",
- "name": "SkipCount",
- "jsonName": null,
- "type": "System.Int32",
- "typeSimple": "number",
- "isOptional": false,
- "defaultValue": null,
- "constraintTypes": null,
- "bindingSourceId": "ModelBinding",
- "descriptorName": "input"
- },
- {
- "nameOnMethod": "input",
- "name": "MaxResultCount",
- "jsonName": null,
- "type": "System.Int32",
- "typeSimple": "number",
- "isOptional": false,
- "defaultValue": null,
- "constraintTypes": null,
- "bindingSourceId": "ModelBinding",
- "descriptorName": "input"
- }
- ],
- "returnValue": {
- "type": "Volo.Abp.Application.Dtos.PagedResultDto",
- "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto"
- },
- "allowAnonymous": null,
- "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService"
}
}
},
@@ -5036,6 +5059,27 @@
}
]
},
+ "Acme.BookStore.Books.AuthorLookupDto": {
+ "baseType": "Volo.Abp.Application.Dtos.EntityDto",
+ "isEnum": false,
+ "enumNames": null,
+ "enumValues": null,
+ "genericArguments": null,
+ "properties": [
+ {
+ "name": "Name",
+ "jsonName": null,
+ "type": "System.String",
+ "typeSimple": "string",
+ "isRequired": false,
+ "minLength": null,
+ "maxLength": null,
+ "minimum": null,
+ "maximum": null,
+ "regex": null
+ }
+ ]
+ },
"Acme.BookStore.Books.BookDto": {
"baseType": "Volo.Abp.Application.Dtos.AuditedEntityDto",
"isEnum": false,
@@ -5090,6 +5134,30 @@
"minimum": null,
"maximum": null,
"regex": null
+ },
+ {
+ "name": "AuthorId",
+ "jsonName": null,
+ "type": "System.Guid",
+ "typeSimple": "string",
+ "isRequired": false,
+ "minLength": null,
+ "maxLength": null,
+ "minimum": null,
+ "maximum": null,
+ "regex": null
+ },
+ {
+ "name": "AuthorName",
+ "jsonName": null,
+ "type": "System.String",
+ "typeSimple": "string",
+ "isRequired": false,
+ "minLength": null,
+ "maxLength": null,
+ "minimum": null,
+ "maximum": null,
+ "regex": null
}
]
},
@@ -5175,6 +5243,18 @@
"minimum": null,
"maximum": null,
"regex": null
+ },
+ {
+ "name": "AuthorId",
+ "jsonName": null,
+ "type": "System.Guid",
+ "typeSimple": "string",
+ "isRequired": false,
+ "minLength": null,
+ "maxLength": null,
+ "minimum": null,
+ "maximum": null,
+ "regex": null
}
]
},
diff --git a/angular/src/app/route.provider.ts b/angular/src/app/route.provider.ts
index 3d2d889..0a75a39 100644
--- a/angular/src/app/route.provider.ts
+++ b/angular/src/app/route.provider.ts
@@ -14,38 +14,36 @@ function configureRoutes(routesService: RoutesService) {
iconClass: 'fas fa-home',
order: 1,
layout: eLayoutType.application,
- },
+ },
{
- path: '/book-store',
- name: '::Menu:BookStore',
- iconClass: 'fas fa-book',
- order: 2,
+ path: '/authors',
+ name: '::Menu:Authors',
+ iconClass: 'fas fa-user-plus',
+ order:2,
layout: eLayoutType.application,
- requiredPolicy: 'BookStore.Books',
+ requiredPolicy: 'BookStore.Authors',
},
{
path: '/books',
- name: '::Menu:Books',
- parentName: '::Menu:BookStore',
+ name: '::Menu:Books',
+ iconClass: 'fas fa-book',
+ order: 3,
layout: eLayoutType.application,
requiredPolicy: 'BookStore.Books',
- },
-
-
-
+ },
{
path: '/customer',
- name: 'Customer',
+ name: '::Menu:Customer',
iconClass: 'fas fa-user',
- order: 2,
+ order: 4,
layout: eLayoutType.application,
requiredPolicy: 'BookStore.Customers',
},
{
path: '/book-issue',
- name: 'book-issue',
+ name: '::Menu:BookIssue',
iconClass: 'fas fa-book',
- order: 2,
+ order: 5,
layout: eLayoutType.application,
requiredPolicy: 'BookStore.BookIssued',
},
diff --git a/aspnet-core/src/Acme.BookStore.Application.Contracts/Books/AuthorLookupDto.cs b/aspnet-core/src/Acme.BookStore.Application.Contracts/Books/AuthorLookupDto.cs
new file mode 100644
index 0000000..3de5d65
--- /dev/null
+++ b/aspnet-core/src/Acme.BookStore.Application.Contracts/Books/AuthorLookupDto.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Volo.Abp.Application.Dtos;
+
+namespace Acme.BookStore.Books
+{
+ public class AuthorLookupDto : EntityDto
+ {
+ public string Name { get; set; }
+ }
+}
diff --git a/aspnet-core/src/Acme.BookStore.Application.Contracts/Books/BookDto.cs b/aspnet-core/src/Acme.BookStore.Application.Contracts/Books/BookDto.cs
index 59f592d..f3359ce 100644
--- a/aspnet-core/src/Acme.BookStore.Application.Contracts/Books/BookDto.cs
+++ b/aspnet-core/src/Acme.BookStore.Application.Contracts/Books/BookDto.cs
@@ -14,5 +14,9 @@ namespace Acme.BookStore.Books
public DateTime PublishDate { get; set; }
public float Price { get; set; }
+
+ public Guid AuthorId { get; set; }
+ public string AuthorName { get; set; }
+
}
}
diff --git a/aspnet-core/src/Acme.BookStore.Application.Contracts/Books/CreateUpdateBookDto.cs b/aspnet-core/src/Acme.BookStore.Application.Contracts/Books/CreateUpdateBookDto.cs
index 07a00c6..b772e05 100644
--- a/aspnet-core/src/Acme.BookStore.Application.Contracts/Books/CreateUpdateBookDto.cs
+++ b/aspnet-core/src/Acme.BookStore.Application.Contracts/Books/CreateUpdateBookDto.cs
@@ -20,5 +20,8 @@ namespace Acme.BookStore.Books
[Required]
public float Price { get; set; }
+
+ public Guid AuthorId { get; set; }
+
}
}
diff --git a/aspnet-core/src/Acme.BookStore.Application.Contracts/Books/IBookAppService.cs b/aspnet-core/src/Acme.BookStore.Application.Contracts/Books/IBookAppService.cs
index f37faa3..27bd118 100644
--- a/aspnet-core/src/Acme.BookStore.Application.Contracts/Books/IBookAppService.cs
+++ b/aspnet-core/src/Acme.BookStore.Application.Contracts/Books/IBookAppService.cs
@@ -15,5 +15,7 @@ namespace Acme.BookStore.Books
CreateUpdateBookDto> //Used to create/update a book
{
Task> GetBookDropDown();
+ Task> GetAuthorLookupAsync();
+
}
}
diff --git a/aspnet-core/src/Acme.BookStore.Application/BookStoreApplicationAutoMapperProfile.cs b/aspnet-core/src/Acme.BookStore.Application/BookStoreApplicationAutoMapperProfile.cs
index 1d6b37f..960c9a4 100644
--- a/aspnet-core/src/Acme.BookStore.Application/BookStoreApplicationAutoMapperProfile.cs
+++ b/aspnet-core/src/Acme.BookStore.Application/BookStoreApplicationAutoMapperProfile.cs
@@ -17,6 +17,7 @@ public class BookStoreApplicationAutoMapperProfile : Profile
// CreateMap, List>().ReverseMap();
CreateMap().ReverseMap();
CreateMap().ReverseMap();
+ CreateMap();
/* You can configure your AutoMapper mapping configuration here.
* Alternatively, you can split your mapping configurations
diff --git a/aspnet-core/src/Acme.BookStore.Application/Books/BookAppService.cs b/aspnet-core/src/Acme.BookStore.Application/Books/BookAppService.cs
index 6a8a204..a502242 100644
--- a/aspnet-core/src/Acme.BookStore.Application/Books/BookAppService.cs
+++ b/aspnet-core/src/Acme.BookStore.Application/Books/BookAppService.cs
@@ -1,43 +1,135 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
+using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
+using Acme.BookStore.Authors;
+using Acme.BookStore.Permissions;
+using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
+using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;
-using Acme.BookStore.Permissions;
-namespace Acme.BookStore.Books
+namespace Acme.BookStore.Books;
+
+[Authorize(BookStorePermissions.Books.Default)]
+public class BookAppService :
+ CrudAppService<
+ Book, //The Book entity
+ BookDto, //Used to show books
+ Guid, //Primary key of the book entity
+ PagedAndSortedResultRequestDto, //Used for paging/sorting
+ CreateUpdateBookDto>, //Used to create/update a book
+ IBookAppService //implement the IBookAppService
{
+ private readonly IAuthorRepository _authorRepository;
+ private readonly IRepository _bookRepository;
+ public BookAppService(
+ IRepository repository,
+ IAuthorRepository authorRepository)
+ : base(repository)
+ {
+ _authorRepository = authorRepository;
+ _bookRepository = repository;
+ GetPolicyName = BookStorePermissions.Books.Default;
+ GetListPolicyName = BookStorePermissions.Books.Default;
+ CreatePolicyName = BookStorePermissions.Books.Create;
+ UpdatePolicyName = BookStorePermissions.Books.Edit;
+ DeletePolicyName = BookStorePermissions.Books.Delete;
+ }
+
+ public override async Task GetAsync(Guid id)
+ {
+ //Get the IQueryable from the repository
+ var queryable = await Repository.GetQueryableAsync();
+
+ //Prepare a query to join books and authors
+ var query = from book in queryable
+ join author in await _authorRepository.GetQueryableAsync() on book.AuthorId equals author.Id
+ where book.Id == id
+ select new { book, author };
+
+ //Execute the query and get the book with author
+ var queryResult = await AsyncExecuter.FirstOrDefaultAsync(query);
+ if (queryResult == null)
+ {
+ throw new EntityNotFoundException(typeof(Book), id);
+ }
+
+ var bookDto = ObjectMapper.Map(queryResult.book);
+ bookDto.AuthorName = queryResult.author.Name;
+ return bookDto;
+ }
+
+ public override async Task> GetListAsync(PagedAndSortedResultRequestDto input)
+ {
+ //Get the IQueryable from the repository
+ var queryable = await Repository.GetQueryableAsync();
+
+ //Prepare a query to join books and authors
+ var query = from book in queryable
+ join author in await _authorRepository.GetQueryableAsync() on book.AuthorId equals author.Id
+ select new { book, author };
- public class BookAppService :
- CrudAppService<
- Book, //The Book entity
- BookDto, //Used to show books
- Guid, //Primary key of the book entity
- PagedAndSortedResultRequestDto, //Used for paging/sorting
- CreateUpdateBookDto>, //Used to create/update a book
- IBookAppService //implement the IBookAppService
+ //Paging
+ query = query
+ .OrderBy(NormalizeSorting(input.Sorting))
+ .Skip(input.SkipCount)
+ .Take(input.MaxResultCount);
+
+ //Execute the query and get a list
+ var queryResult = await AsyncExecuter.ToListAsync(query);
+
+ //Convert the query result to a list of BookDto objects
+ var bookDtos = queryResult.Select(x =>
+ {
+ var bookDto = ObjectMapper.Map(x.book);
+ bookDto.AuthorName = x.author.Name;
+ return bookDto;
+ }).ToList();
+
+ //Get the total count with another query
+ var totalCount = await Repository.GetCountAsync();
+
+ return new PagedResultDto(
+ totalCount,
+ bookDtos
+ );
+ }
+
+ public async Task> GetAuthorLookupAsync()
{
- private readonly IRepository _bookRepository;
- public BookAppService(IRepository repository)
- : base(repository)
+ var authors = await _authorRepository.GetListAsync();
+
+ return new ListResultDto(
+ ObjectMapper.Map, List>(authors)
+ );
+ }
+
+ private static string NormalizeSorting(string sorting)
+ {
+ if (sorting.IsNullOrEmpty())
{
- _bookRepository = repository;
- GetPolicyName = BookStorePermissions.Books.Default;
- GetListPolicyName = BookStorePermissions.Books.Default;
- CreatePolicyName = BookStorePermissions.Books.Create;
- UpdatePolicyName = BookStorePermissions.Books.Edit;
- DeletePolicyName = BookStorePermissions.Books.Delete;
+ return $"book.{nameof(Book.Name)}";
}
- public async Task> GetBookDropDown()
+ if (sorting.Contains("authorName", StringComparison.OrdinalIgnoreCase))
{
- var cus = await _bookRepository.GetListAsync();
- cus = cus == null ? new List() : cus;
- return ObjectMapper.Map, List>(cus);
+ return sorting.Replace(
+ "authorName",
+ "author.Name",
+ StringComparison.OrdinalIgnoreCase
+ );
}
+ return $"book.{sorting}";
+ }
+
+ public async Task> GetBookDropDown()
+ {
+ var cus = await _bookRepository.GetListAsync();
+ cus = cus == null ? new List() : cus;
+ return ObjectMapper.Map, List>(cus);
}
}
diff --git a/aspnet-core/src/Acme.BookStore.Domain.Shared/Localization/BookStore/en.json b/aspnet-core/src/Acme.BookStore.Domain.Shared/Localization/BookStore/en.json
index 90017c9..5c2e2c8 100644
--- a/aspnet-core/src/Acme.BookStore.Domain.Shared/Localization/BookStore/en.json
+++ b/aspnet-core/src/Acme.BookStore.Domain.Shared/Localization/BookStore/en.json
@@ -6,6 +6,8 @@
"LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io.",
"Menu:BookStore": "Book Store",
"Menu:Books": "Books",
+ "Menu:Customer": "Customer",
+ "Menu:BookIssue": "Book Issue",
"Actions": "Actions",
"Close": "Close",
"Delete": "Delete",
@@ -46,7 +48,12 @@
"Permission:BookIssued": "Book Issued Management",
"Permission:BookIssued.Create": "Creating new Issued Book",
"Permission:BookIssued.Edit": "Editing the Issued Book",
- "Permission:BookIssued.Delete": "Deleting the Issued Book"
+ "Permission:BookIssued.Delete": "Deleting the Issued Book",
+ "Menu:Authors": "Authors",
+ "Authors": "Authors",
+ "AuthorDeletionConfirmationMessage": "Are you sure to delete the author '{0}'?",
+ "BirthDate": "Birth date",
+ "NewAuthor": "New author"
}
}
diff --git a/aspnet-core/src/Acme.BookStore.Domain/BookStoreDataSeederContributor.cs b/aspnet-core/src/Acme.BookStore.Domain/BookStoreDataSeederContributor.cs
index 7367aca..5e5751f 100644
--- a/aspnet-core/src/Acme.BookStore.Domain/BookStoreDataSeederContributor.cs
+++ b/aspnet-core/src/Acme.BookStore.Domain/BookStoreDataSeederContributor.cs
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using Acme.BookStore.Books;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
@@ -23,7 +23,7 @@ namespace Acme.BookStore
private readonly CustomerManager _customerManager;
public BookStoreDataSeederContributor(IRepository bookRepository,
- IAuthorRepository authorRepository,
+ IAuthorRepository authorRepository,
AuthorManager authorManager,
ICustomerRepository customerRepository,
CustomerManager customerManager
@@ -40,48 +40,76 @@ namespace Acme.BookStore
public async Task SeedAsync(DataSeedContext context)
{
- if (await _bookRepository.GetCountAsync() <= 0)
- {
- await _bookRepository.InsertAsync(
- new Book
- {
- Name = "1984",
- Type = BookType.Dystopia,
- PublishDate = new DateTime(1949, 6, 8),
- Price = 19.84f
- },
- autoSave: true
- );
+ //if (await _bookRepository.GetCountAsync() <= 0)
+ //{
+ // await _bookRepository.InsertAsync(
+ // new Book
+ // {
+ // Name = "1984",
+ // Type = BookType.Dystopia,
+ // PublishDate = new DateTime(1949, 6, 8),
+ // Price = 19.84f
+ // },
+ // autoSave: true
+ // );
- await _bookRepository.InsertAsync(
- new Book
- {
- Name = "The Hitchhiker's Guide to the Galaxy",
- Type = BookType.ScienceFiction,
- PublishDate = new DateTime(1995, 9, 27),
- Price = 42.0f
- },
- autoSave: true
- );
- }
+ // await _bookRepository.InsertAsync(
+ // new Book
+ // {
+ // Name = "The Hitchhiker's Guide to the Galaxy",
+ // Type = BookType.ScienceFiction,
+ // PublishDate = new DateTime(1995, 9, 27),
+ // Price = 42.0f
+ // },
+ // autoSave: true
+ // );
+ //}
if (await _authorRepository.GetCountAsync() <= 0)
{
- await _authorRepository.InsertAsync(
+ var orwell = await _authorRepository.InsertAsync(
await _authorManager.CreateAsync(
"George Orwell",
new DateTime(1903, 06, 25),
"Orwell produced literary criticism and poetry, fiction and polemical journalism; and is best known for the allegorical novella Animal Farm (1945) and the dystopian novel Nineteen Eighty-Four (1949)."
)
);
- await _authorRepository.InsertAsync(
+ var douglas = await _authorRepository.InsertAsync(
await _authorManager.CreateAsync(
"Douglas Adams",
new DateTime(1952, 03, 11),
"Douglas Adams was an English author, screenwriter, essayist, humorist, satirist and dramatist. Adams was an advocate for environmentalism and conservation, a lover of fast cars, technological innovation and the Apple Macintosh, and a self-proclaimed 'radical atheist'."
)
);
+
+ if (await _bookRepository.GetCountAsync() <= 0)
+ {
+ await _bookRepository.InsertAsync(
+ new Book
+ {
+ AuthorId = orwell.Id, // SET THE AUTHOR
+ Name = "1984",
+ Type = BookType.Dystopia,
+ PublishDate = new DateTime(1949, 6, 8),
+ Price = 19.84f
+ },
+ autoSave: true
+ );
+
+ await _bookRepository.InsertAsync(
+ new Book
+ {
+ AuthorId = douglas.Id, // SET THE AUTHOR
+ Name = "The Hitchhiker's Guide to the Galaxy",
+ Type = BookType.ScienceFiction,
+ PublishDate = new DateTime(1995, 9, 27),
+ Price = 42.0f
+ },
+ autoSave: true
+ );
+ }
+
}
if (await _customerRepository.GetCountAsync() <= 0)
diff --git a/aspnet-core/src/Acme.BookStore.Domain/Books/Book.cs b/aspnet-core/src/Acme.BookStore.Domain/Books/Book.cs
index 7f9717c..b3e5c05 100644
--- a/aspnet-core/src/Acme.BookStore.Domain/Books/Book.cs
+++ b/aspnet-core/src/Acme.BookStore.Domain/Books/Book.cs
@@ -16,5 +16,7 @@ namespace Acme.BookStore.Books
public DateTime PublishDate { get; set; }
public float Price { get; set; }
+ public Guid AuthorId { get; set; }
+
}
}
diff --git a/aspnet-core/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs b/aspnet-core/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs
index b29915f..c3aa130 100644
--- a/aspnet-core/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs
+++ b/aspnet-core/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs
@@ -93,6 +93,8 @@ public class BookStoreDbContext :
BookStoreConsts.DbSchema);
b.ConfigureByConvention(); //auto configure for the base class props
b.Property(x => x.Name).IsRequired().HasMaxLength(128);
+
+ b.HasOne().WithMany().HasForeignKey(x => x.AuthorId).IsRequired();
});
builder.Entity(b =>
diff --git a/aspnet-core/src/Acme.BookStore.EntityFrameworkCore/Migrations/20240612062933_Added_AuthorId_To_Book.Designer.cs b/aspnet-core/src/Acme.BookStore.EntityFrameworkCore/Migrations/20240612062933_Added_AuthorId_To_Book.Designer.cs
new file mode 100644
index 0000000..b64132a
--- /dev/null
+++ b/aspnet-core/src/Acme.BookStore.EntityFrameworkCore/Migrations/20240612062933_Added_AuthorId_To_Book.Designer.cs
@@ -0,0 +1,2220 @@
+//
+using System;
+using Acme.BookStore.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Volo.Abp.EntityFrameworkCore;
+
+#nullable disable
+
+namespace Acme.BookStore.Migrations
+{
+ [DbContext(typeof(BookStoreDbContext))]
+ [Migration("20240612062933_Added_AuthorId_To_Book")]
+ partial class Added_AuthorId_To_Book
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
+ .HasAnnotation("ProductVersion", "8.0.0")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("Acme.BookStore.Authors.Author", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("BirthDate")
+ .HasColumnType("datetime2");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("CreatorId");
+
+ b.Property("DeleterId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("DeletionTime");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("IsDeleted");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("LastModifierId");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("ShortBio")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Name");
+
+ b.ToTable("AppAuthors", (string)null);
+ });
+
+ modelBuilder.Entity("Acme.BookStore.BookIssued.BookIssue", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("BookId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("CreatorId");
+
+ b.Property("CustomerId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeleterId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("DeletionTime");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("IsDeleted");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("LastModifierId");
+
+ b.HasKey("Id");
+
+ b.ToTable("AppBookIssued", (string)null);
+ });
+
+ modelBuilder.Entity("Acme.BookStore.Books.Book", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuthorId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("CreatorId");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("LastModifierId");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property("Price")
+ .HasColumnType("real");
+
+ b.Property("PublishDate")
+ .HasColumnType("datetime2");
+
+ b.Property("Type")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuthorId");
+
+ b.ToTable("AppBooks", (string)null);
+ });
+
+ modelBuilder.Entity("Acme.BookStore.Customers.Customer", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Address")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("CreatorId");
+
+ b.Property("DeleterId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("DeletionTime");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("FirstName")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("nvarchar(100)");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("IsDeleted");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("LastModifierId");
+
+ b.Property("LastName")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("nvarchar(100)");
+
+ b.Property("Phone")
+ .IsRequired()
+ .HasMaxLength(14)
+ .HasColumnType("nvarchar(14)");
+
+ b.HasKey("Id");
+
+ b.ToTable("AppCustomers", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ApplicationName")
+ .HasMaxLength(96)
+ .HasColumnType("nvarchar(96)")
+ .HasColumnName("ApplicationName");
+
+ b.Property("BrowserInfo")
+ .HasMaxLength(512)
+ .HasColumnType("nvarchar(512)")
+ .HasColumnName("BrowserInfo");
+
+ b.Property("ClientId")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)")
+ .HasColumnName("ClientId");
+
+ b.Property("ClientIpAddress")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)")
+ .HasColumnName("ClientIpAddress");
+
+ b.Property("ClientName")
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)")
+ .HasColumnName("ClientName");
+
+ b.Property("Comments")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("Comments");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CorrelationId")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)")
+ .HasColumnName("CorrelationId");
+
+ b.Property("Exceptions")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("ExecutionDuration")
+ .HasColumnType("int")
+ .HasColumnName("ExecutionDuration");
+
+ b.Property("ExecutionTime")
+ .HasColumnType("datetime2");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("HttpMethod")
+ .HasMaxLength(16)
+ .HasColumnType("nvarchar(16)")
+ .HasColumnName("HttpMethod");
+
+ b.Property("HttpStatusCode")
+ .HasColumnType("int")
+ .HasColumnName("HttpStatusCode");
+
+ b.Property("ImpersonatorTenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("ImpersonatorTenantId");
+
+ b.Property("ImpersonatorTenantName")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)")
+ .HasColumnName("ImpersonatorTenantName");
+
+ b.Property("ImpersonatorUserId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("ImpersonatorUserId");
+
+ b.Property("ImpersonatorUserName")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("ImpersonatorUserName");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.Property("TenantName")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)")
+ .HasColumnName("TenantName");
+
+ b.Property("Url")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("Url");
+
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("UserId");
+
+ b.Property("UserName")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("UserName");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "ExecutionTime");
+
+ b.HasIndex("TenantId", "UserId", "ExecutionTime");
+
+ b.ToTable("AbpAuditLogs", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditLogId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("AuditLogId");
+
+ b.Property("ExecutionDuration")
+ .HasColumnType("int")
+ .HasColumnName("ExecutionDuration");
+
+ b.Property("ExecutionTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("ExecutionTime");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("MethodName")
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)")
+ .HasColumnName("MethodName");
+
+ b.Property("Parameters")
+ .HasMaxLength(2000)
+ .HasColumnType("nvarchar(2000)")
+ .HasColumnName("Parameters");
+
+ b.Property("ServiceName")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("ServiceName");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuditLogId");
+
+ b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime");
+
+ b.ToTable("AbpAuditLogActions", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditLogId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("AuditLogId");
+
+ b.Property("ChangeTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("ChangeTime");
+
+ b.Property("ChangeType")
+ .HasColumnType("tinyint")
+ .HasColumnName("ChangeType");
+
+ b.Property("EntityId")
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)")
+ .HasColumnName("EntityId");
+
+ b.Property("EntityTenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("EntityTypeFullName")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)")
+ .HasColumnName("EntityTypeFullName");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuditLogId");
+
+ b.HasIndex("TenantId", "EntityTypeFullName", "EntityId");
+
+ b.ToTable("AbpEntityChanges", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("EntityChangeId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("NewValue")
+ .HasMaxLength(512)
+ .HasColumnType("nvarchar(512)")
+ .HasColumnName("NewValue");
+
+ b.Property("OriginalValue")
+ .HasMaxLength(512)
+ .HasColumnType("nvarchar(512)")
+ .HasColumnName("OriginalValue");
+
+ b.Property("PropertyName")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)")
+ .HasColumnName("PropertyName");
+
+ b.Property("PropertyTypeFullName")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)")
+ .HasColumnName("PropertyTypeFullName");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("EntityChangeId");
+
+ b.ToTable("AbpEntityPropertyChanges", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("IsAbandoned")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("JobArgs")
+ .IsRequired()
+ .HasMaxLength(1048576)
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("JobName")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property("LastTryTime")
+ .HasColumnType("datetime2");
+
+ b.Property("NextTryTime")
+ .HasColumnType("datetime2");
+
+ b.Property("Priority")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("tinyint")
+ .HasDefaultValue((byte)15);
+
+ b.Property("TryCount")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("smallint")
+ .HasDefaultValue((short)0);
+
+ b.HasKey("Id");
+
+ b.HasIndex("IsAbandoned", "NextTryTime");
+
+ b.ToTable("AbpBackgroundJobs", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AllowedProviders")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("DefaultValue")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("Description")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("DisplayName")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("GroupName")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property("IsAvailableToHost")
+ .HasColumnType("bit");
+
+ b.Property("IsVisibleToClients")
+ .HasColumnType("bit");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property("ParentName")
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property("ValueType")
+ .HasMaxLength(2048)
+ .HasColumnType("nvarchar(2048)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("GroupName");
+
+ b.HasIndex("Name")
+ .IsUnique();
+
+ b.ToTable("AbpFeatures", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DisplayName")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Name")
+ .IsUnique();
+
+ b.ToTable("AbpFeatureGroups", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property("ProviderKey")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("ProviderName")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Name", "ProviderName", "ProviderKey")
+ .IsUnique()
+ .HasFilter("[ProviderName] IS NOT NULL AND [ProviderKey] IS NOT NULL");
+
+ b.ToTable("AbpFeatureValues", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("Description")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("IsStatic")
+ .HasColumnType("bit");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("Regex")
+ .HasMaxLength(512)
+ .HasColumnType("nvarchar(512)");
+
+ b.Property("RegexDescription")
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property("Required")
+ .HasColumnType("bit");
+
+ b.Property("ValueType")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("AbpClaimTypes", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("SourceTenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("SourceUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TargetTenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TargetUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId")
+ .IsUnique()
+ .HasFilter("[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL");
+
+ b.ToTable("AbpLinkUsers", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("EntityVersion")
+ .HasColumnType("int");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("IsDefault")
+ .HasColumnType("bit")
+ .HasColumnName("IsDefault");
+
+ b.Property("IsPublic")
+ .HasColumnType("bit")
+ .HasColumnName("IsPublic");
+
+ b.Property("IsStatic")
+ .HasColumnType("bit")
+ .HasColumnName("IsStatic");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("NormalizedName")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("NormalizedName");
+
+ b.ToTable("AbpRoles", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ClaimType")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("ClaimValue")
+ .HasMaxLength(1024)
+ .HasColumnType("nvarchar(1024)");
+
+ b.Property("RoleId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("AbpRoleClaims", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Action")
+ .HasMaxLength(96)
+ .HasColumnType("nvarchar(96)");
+
+ b.Property("ApplicationName")
+ .HasMaxLength(96)
+ .HasColumnType("nvarchar(96)");
+
+ b.Property("BrowserInfo")
+ .HasMaxLength(512)
+ .HasColumnType("nvarchar(512)");
+
+ b.Property("ClientId")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("ClientIpAddress")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CorrelationId")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("Identity")
+ .HasMaxLength(96)
+ .HasColumnType("nvarchar(96)");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.Property("TenantName")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("UserName")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "Action");
+
+ b.HasIndex("TenantId", "ApplicationName");
+
+ b.HasIndex("TenantId", "Identity");
+
+ b.HasIndex("TenantId", "UserId");
+
+ b.ToTable("AbpSecurityLogs", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AccessFailedCount")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int")
+ .HasDefaultValue(0)
+ .HasColumnName("AccessFailedCount");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("CreatorId");
+
+ b.Property("DeleterId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("DeletionTime");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("Email");
+
+ b.Property("EmailConfirmed")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("EmailConfirmed");
+
+ b.Property("EntityVersion")
+ .HasColumnType("int");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("IsActive")
+ .HasColumnType("bit")
+ .HasColumnName("IsActive");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("IsDeleted");
+
+ b.Property