diff --git a/docs/en/Background-Workers.md b/docs/en/Background-Workers.md index 2e1b9d2a90..8225aac2a6 100644 --- a/docs/en/Background-Workers.md +++ b/docs/en/Background-Workers.md @@ -80,7 +80,7 @@ public class PassiveUserCheckerWorker : AsyncPeriodicBackgroundWorkerBase ## Register Background Worker -After creating a background worker class, you should to add it to the `IBackgroundWorkerManager`. The most common place is the `OnApplicationInitialization` method of your module class: +After creating a background worker class, you should add it to the `IBackgroundWorkerManager`. The most common place is the `OnApplicationInitialization` method of your module class: ````csharp [DependsOn(typeof(AbpBackgroundWorkersModule))] @@ -137,4 +137,4 @@ ABP Framework's background worker system is good to implement periodic tasks. Ho ## See Also * [Quartz Integration for the background workers](Background-Workers-Quartz.md) -* [Background Jobs](Background-Jobs.md) \ No newline at end of file +* [Background Jobs](Background-Jobs.md) diff --git a/docs/en/CLI.md b/docs/en/CLI.md index ef920d1453..0154643c9b 100644 --- a/docs/en/CLI.md +++ b/docs/en/CLI.md @@ -105,7 +105,7 @@ abp new Acme.BookStore * `--preview`: Use latest preview version. * `--template-source` or `-ts`: Specifies a custom template source to use to build the project. Local and network sources can be used(Like `D:\local-template` or `https://.../my-template-file.zip`). * `--create-solution-folder` or `-csf`: Specifies if the project will be in a new folder in the output folder or directly the output folder. -* `--connection-string` or `-cs`: Overwrites the default connection strings in all `appsettings.json` files. The default connection string is `Server=localhost;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true` for EF Core and it is configured to use the SQL Server. If you want to use the EF Core, but need to change the DBMS, you can change it as [described here](Entity-Framework-Core-Other-DBMS.md) (after creating the solution). +* `--connection-string` or `-cs`: Overwrites the default connection strings in all `appsettings.json` files. The default connection string is `Server=localhost;Database=MyProjectName;Trusted_Connection=True` for EF Core and it is configured to use the SQL Server. If you want to use the EF Core, but need to change the DBMS, you can change it as [described here](Entity-Framework-Core-Other-DBMS.md) (after creating the solution). * `--database-management-system` or `-dbms`: Sets the database management system. Default is **SQL Server**. Supported DBMS's: * `SqlServer` * `MySQL` diff --git a/docs/en/Contribution/Index.md b/docs/en/Contribution/Index.md index 07dc73ab24..d2525ae191 100644 --- a/docs/en/Contribution/Index.md +++ b/docs/en/Contribution/Index.md @@ -10,7 +10,7 @@ If you want to write **articles** or **how to guides** related to the ABP Framew You can always send pull requests to the GitHub repository. -- Clone the [ABP repository](https://github.com/abpframework/abp/) from GitHub. +- [Fork](https://docs.github.com/en/free-pro-team@latest/github/getting-started-with-github/fork-a-repo) the [ABP repository](https://github.com/abpframework/abp/) from GitHub. - Build the repository using the `/build/build-all.ps1 -f` for one time. - Make the necessary changes, including unit/integration tests. - Send a pull request. diff --git a/docs/en/Customizing-Application-Modules-Guide.md b/docs/en/Customizing-Application-Modules-Guide.md index d184d82906..56b94ae4fc 100644 --- a/docs/en/Customizing-Application-Modules-Guide.md +++ b/docs/en/Customizing-Application-Modules-Guide.md @@ -43,17 +43,59 @@ In any case, you can create a **separate solution** for the desired module and d #### Publishing the Customized Module as Packages -One alternative scenario could be re-packaging the module source code (as NuGet/NPM packages) and using as package references. You can use a local private NuGet/NPM server for your company. +One alternative scenario could be re-packaging the module source code (as NuGet/NPM packages) and using as package references. You can use a local private NuGet/NPM server for your company, for example. ## Module Customization / Extending Approaches -This section suggests some approaches if you decided to use pre-built application modules as NuGet/NPM package references. The following documents explain how to customize/extend existing modules in different ways: +This section suggests some approaches if you decided to use pre-built application modules as NuGet/NPM package references. The following documents explain how to customize/extend existing modules in different ways. + +### Module Entity Extension System + +> Module entity extension system is the **main and high level extension system** that allows you to **define new properties** for existing entities of the depended modules. It automatically **adds properties to the entity, database, HTTP API and the user interface** in a single point. + +See the [Module Entity Extensions document](Module-Entity-Extensions.md) to learn how to use it. + +### Extending Entities + +If you only need to get/set extra data on an existing entity, follow the [Extending Entities](Customizing-Application-Modules-Extending-Entities.md) document. + +### Overriding Services/Components + +In addition to the extensibility systems, you can partially or completely override any service or user interface page/component. -* [Extending Entities](Customizing-Application-Modules-Extending-Entities.md) * [Overriding Services](Customizing-Application-Modules-Overriding-Services.md) * [Overriding the User Interface](Customizing-Application-Modules-Overriding-User-Interface.md) -### See Also +### Additional UI Extensibility Points + +There are some low level systems that you can control entity actions, table columns and page toolbar of a page defined by a module. + +#### Entity Actions + +Entity action extension system allows you to add a new action to the action menu for an entity on the user interface; + +* [Entity Action Extensions for ASP.NET Core UI](UI/AspNetCore/Entity-Action-Extensions.md) +* [Entity Action Extensions for Angular](UI/Angular/Entity-Action-Extensions.md) + +#### Data Table Column Extensions + +Data table column extension system allows you to add a new column in the data table on the user interface; + +* [Data Table Column Extensions for ASP.NET Core UI](UI/AspNetCore/Data-Table-Column-Extensions.md) +* [Data Table Column Extensions for Angular](UI/Angular/Data-Table-Column-Extensions.md) + +#### Page Toolbar + +Page toolbar system allows you to add components to the toolbar of a page; + +* [Page Toolbar Extensions for ASP.NET Core UI](UI/AspNetCore/Page-Toolbar-Extensions.md) +* [Page Toolbar Extensions for Angular](UI/Angular/Page-Toolbar-Extensions.md) + +#### Others + +* [Dynamic Form Extensions for Angular](UI/Angular/Dynamic-Form-Extensions.md) + +## See Also Also, see the following documents: diff --git a/docs/en/Emailing.md b/docs/en/Emailing.md index aa341a3898..a98874165d 100644 --- a/docs/en/Emailing.md +++ b/docs/en/Emailing.md @@ -223,7 +223,7 @@ Pathes of the templates in the virtual file system are shown below: * `/Volo/Abp/Emailing/Templates/Layout.tpl` * `/Volo/Abp/Emailing/Templates/Message.tpl` -If you add files to the same localization in the virtual file system, your files will override them. +If you add files to the same location in the virtual file system, your files will override them. Templates are inline localized, that means you can take the power of the [localization system](Localization.md) to make your templates multi-cultural. @@ -247,4 +247,4 @@ So, don't confuse if you don't receive emails on DEBUG mode. Emails will be sent ## See Also -* [MailKit integration for sending emails](MailKit.md) \ No newline at end of file +* [MailKit integration for sending emails](MailKit.md) diff --git a/docs/en/Entity-Framework-Core-Migrations.md b/docs/en/Entity-Framework-Core-Migrations.md index a93ee217da..be5968a9af 100644 --- a/docs/en/Entity-Framework-Core-Migrations.md +++ b/docs/en/Entity-Framework-Core-Migrations.md @@ -586,7 +586,7 @@ First step is to change the connection string section inside all the `appsetting ````json "ConnectionStrings": { - "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True" } ```` @@ -594,10 +594,10 @@ Change it as shown below: ````json "ConnectionStrings": { - "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True;MultipleActiveResultSets=true", - "AbpPermissionManagement": "Server=localhost;Database=BookStore_SecondDb;Trusted_Connection=True;MultipleActiveResultSets=true", - "AbpSettingManagement": "Server=localhost;Database=BookStore_SecondDb;Trusted_Connection=True;MultipleActiveResultSets=true", - "AbpAuditLogging": "Server=localhost;Database=BookStore_SecondDb;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True", + "AbpPermissionManagement": "Server=localhost;Database=BookStore_SecondDb;Trusted_Connection=True", + "AbpSettingManagement": "Server=localhost;Database=BookStore_SecondDb;Trusted_Connection=True", + "AbpAuditLogging": "Server=localhost;Database=BookStore_SecondDb;Trusted_Connection=True" } ```` diff --git a/docs/en/Modules/Docs.md b/docs/en/Modules/Docs.md index 5780b4b827..35478d9ce0 100644 --- a/docs/en/Modules/Docs.md +++ b/docs/en/Modules/Docs.md @@ -47,7 +47,7 @@ The database connection string is located in `appsettings.json` of your `Acme.My ```json { "ConnectionStrings": { - "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProject;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProject;Trusted_Connection=True" } } ``` diff --git a/docs/en/Samples/Microservice-Demo.md b/docs/en/Samples/Microservice-Demo.md index 492dfb203b..285c2b10a0 100644 --- a/docs/en/Samples/Microservice-Demo.md +++ b/docs/en/Samples/Microservice-Demo.md @@ -842,7 +842,7 @@ It has a dedicated MongoDB database (MsDemo_Blogging) to store blog and posts. I ````json "ConnectionStrings": { - "Default": "Server=localhost;Database=MsDemo_Identity;Trusted_Connection=True;MultipleActiveResultSets=true", + "Default": "Server=localhost;Database=MsDemo_Identity;Trusted_Connection=True", "Blogging": "mongodb://localhost/MsDemo_Blogging" } ```` @@ -968,8 +968,8 @@ There are two connection strings in the `appsettings.json` file: ````json "ConnectionStrings": { - "Default": "Server=localhost;Database=MsDemo_Identity;Trusted_Connection=True;MultipleActiveResultSets=true", - "ProductManagement": "Server=localhost;Database=MsDemo_ProductManagement;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=localhost;Database=MsDemo_Identity;Trusted_Connection=True", + "ProductManagement": "Server=localhost;Database=MsDemo_ProductManagement;Trusted_Connection=True" } ```` diff --git a/docs/en/UI/Angular/Data-Table-Column-Extensions.md b/docs/en/UI/Angular/Data-Table-Column-Extensions.md new file mode 100644 index 0000000000..cd2df5cf4f --- /dev/null +++ b/docs/en/UI/Angular/Data-Table-Column-Extensions.md @@ -0,0 +1,327 @@ +# Data Table Column (or Entity Prop) Extensions for Angular UI + + +## Introduction + +Entity prop extension system allows you to add a new column to the data table for an entity or change/remove an already existing one. A "Name" column was added to the user management page below: + +![Entity Prop Extension Example: "Name" Column](images/user-prop-extension-name-column-ng.png) + +You will have access to the current entity in your code and display its value, make the column sortable, perform visibility checks, and more. You can also render custom HTML in table cells. + +## How to Set Up + +In this example, we will add a "Name" column and display the value of the `name` field in the user management page of the [Identity Module](../../Modules/Identity.md). + +### Step 1. Create Entity Prop Contributors + +The following code prepares a constant named `identityEntityPropContributors`, ready to be imported and used in your root module: + +```js +// entity-prop-contributors.ts + +import { EntityProp, EntityPropList, ePropType } from '@abp/ng.theme.shared/extensions'; +import { IdentityEntityPropContributors, IdentityUserDto } from '@volo/abp.ng.identity'; + +const nameProp = new EntityProp({ + type: ePropType.String, + name: 'name', + displayName: 'AbpIdentity::Name', + sortable: true, + columnWidth: 250, +}); + +export function namePropContributor(propList: EntityPropList) { + propList.addAfter( + nameProp, + 'userName', + (value, name) => value.name === name, + ); +} + +export const identityEntityPropContributors: IdentityEntityPropContributors = { + 'Identity.UsersComponent': [namePropContributor], +}; + +``` + +The list of props, conveniently named as `propList`, is a **doubly linked list**. That is why we have used the `addAfter` method, which adds a node with given value after the first node that has the previous value. You may find [all available methods here](../Common/Utils/Linked-List.md). + +> **Important Note 1:** AoT compilation does not support function calls in decorator metadata. This is why we have defined `namePropContributor` as an exported function declaration here. Please do not forget exporting your contributor callbacks and forget about lambda functions (a.k.a. arrow functions). Please refer to [AoT metadata errors](https://angular.io/guide/aot-metadata-errors#function-calls-not-supported) for details. + +> **Important Note 2:** Please use one of the following if Ivy is not enabled in your project. Otherwise, you will get an "Expression form not supported." error. + +```js +export const identityEntityPropContributors: IdentityEntityPropContributors = { + 'Identity.UsersComponent': [ namePropContributor ], +}; + +/* OR */ + +const identityContributors: IdentityEntityPropContributors = {}; +identityContributors[eIdentityComponents.Users] = [ namePropContributor ]; +export const identityEntityPropContributors = identityContributors; +``` + +### Step 2. Import and Use Entity Prop Contributors + +Import `identityEntityPropContributors` in your routing module and pass it to the static `forLazy` method of `IdentityModule` as seen below: + +```js +import { identityEntityPropContributors } from './entity-prop-contributors'; + +const routes: Routes = [ + { + path: '', + component: DynamicLayoutComponent, + children: [ + { + path: 'identity', + loadChildren: () => + import('@volo/abp.ng.identity').then(m => + m.IdentityModule.forLazy({ + entityPropContributors: identityEntityPropContributors, + }), + ), + }, + // other child routes + ], + // other routes + } +]; +``` + +That is it, `nameProp` entity prop will be added, and you will see the "Name" column next to the usernames on the grid in the users page (`UsersComponent`) of the `IdentityModule`. + +## How to Render Custom HTML in Cells + +You can use the `valueResolver` to render an HTML string in the table. Imagine we want to show a red times icon (❌) next to unconfirmed emails and phones, instead of showing a green check icon next to confirmed emails and phones. The contributors below would do that for you. + +```js +// entity-prop-contributors.ts + +import { EntityProp, EntityPropList, ePropType } from '@abp/ng.theme.shared/extensions'; +import { IdentityUserDto } from '@volo/abp.ng.identity'; +import { IdentityEntityPropContributors } from '@volo/abp.ng.identity/config'; + +export function emailPropContributor(propList: EntityPropList) { + const index = propList.indexOf('email', (value, name) => value.name === name); + const droppedNode = propList.dropByIndex(index); + const emailProp = new EntityProp({ + ...droppedNode.value, + valueResolver: data => { + const { email, emailConfirmed } = data.record; + const icon = email && !emailConfirmed ? `` : ''; + + return of((email || '') + icon); // should return an observable + }, + }); + + propList.addByIndex(emailProp, index); +} + +export function phonePropContributor(propList: EntityPropList) { + const index = propList.indexOf('phoneNumber', (value, name) => value.name === name); + const droppedNode = propList.dropByIndex(index); + const phoneProp = new EntityProp({ + ...droppedNode.value, + valueResolver: data => { + const { phoneNumber, phoneNumberConfirmed } = data.record; + const icon = + phoneNumber && !phoneNumberConfirmed ? `` : ''; + + return of((phoneNumber || '') + icon); // should return an observable + }, + }); + + propList.addByIndex(phoneProp, index); +} + +export const identityEntityPropContributors: IdentityEntityPropContributors = { + 'Identity.UsersComponent': [emailPropContributor, phonePropContributor], +}; + +``` + +> The `valueResolver` method should return an observable. You can wrap your return values with `of` from RxJS for that. + +## Object Extensions + +Extra properties defined on an existing entity will be included in the table based on their configuration. The values will also be mapped to and from `extraProperties` automatically. They are available when defining custom contributors, so you can drop, modify, or reorder them. The `isExtra` identifier will be set to `true` for these properties and will define this automatic behavior. + +## API + +### PropData\ + +`PropData` is the shape of the parameter passed to all callbacks or predicates in an `EntityProp`. + +It has the following properties: + +- **record** is the row data, i.e. current value rendered in the table. + + ```js + { + type: ePropType.String, + name: 'name', + valueResolver: data => { + const name = data.record.name || ''; + return of(name.toUpperCase()); + }, + } + ``` + +- **index** is the table index where the record is at. + +- **getInjected** is the equivalent of [Injector.get](https://angular.io/api/core/Injector#get). You can use it to reach injected dependencies of `ExtensibleTableComponent`, including, but not limited to, its parent component. + + ```js + { + type: ePropType.String, + name: 'name', + valueResolver: data => { + const restService = data.getInjected(RestService); + const usersComponent = data.getInjected(UsersComponent); + + // Use restService and usersComponent public props and methods here + }, + } + ``` + +### PropCallback\ + +`PropCallback` is the type of the callback function that can be passed to an `EntityProp` as `prop` parameter. A prop callback gets a single parameter, the `PropData`. The return type may be anything, including `void`. Here is a simplified representation: + +```js +type PropCallback = (data?: PropData) => R; +``` + +### PropPredicate\ + +`PropPredicate` is the type of the predicate function that can be passed to an `EntityProp` as `visible` parameter. A prop predicate gets a single parameter, the `PropData`. The return type must be `boolean`. Here is a simplified representation: + +```js +type PropPredicate = (data?: PropData) => boolean; +``` + +### EntityPropOptions\ + +`EntityPropOptions` is the type that defines required and optional properties you have to pass in order to create an entity prop. + +Its type definition is as follows: + +```js +type EntityPropOptions = { + type: ePropType; + name: string; + displayName?: string; + valueResolver?: PropCallback>; + sortable?: boolean; + columnWidth?: number; + permission?: string; + visible?: PropPredicate; +}; +``` + +As you see, passing `type` and `name` is enough to create an entity prop. Here is what each property is good for: + +- **type** is the type of the prop value. It is used for custom rendering in the table. (_required_) +- **name** is the property name (or key) which will be used to read the value of the prop. (_required_) +- **displayName** is the name of the property which will be localized and shown as column header. (_default:_ `options.name`) +- **valueResolver** is a callback that is called when the cell is rendered. It must return an observable. (_default:_ `data => of(data.record[options.name])`) +- **sortable** defines if the table is sortable based on this entity prop. Sort icons are shown based on it. (_default:_ `false`) +- **columnWidth** defines a minimum width for the column. Good for horizontal scroll. (_default:_ `undefined`) +- **permission** is the permission context which will be used to decide if a column for this entity prop should be displayed to the user or not. (_default:_ `undefined`) +- **visible** is a predicate that will be used to decide if this entity prop should be displayed on the table or not. (_default:_ `() => true`) + +> Important Note: Do not use record in visibility predicates. First of all, the table header checks it too and the record will be `undefined`. Second, if some cells are displayed and others are not, the table will be broken. Use the `valueResolver` and render an empty cell when you need to hide a specific cell. + +You may find a full example below. + +### EntityProp\ + +`EntityProp` is the class that defines your entity props. It takes an `EntityPropOptions` and sets the default values to the properties, creating an entity prop that can be passed to an entity contributor. + +```js +const options: EntityPropOptions = { + type: ePropType.String, + name: 'email', + displayName: 'AbpIdentity::EmailAddress', + valueResolver: data => { + const { email, emailConfirmed } = data.record; + + return of( + (email || '') + (emailConfirmed ? `` : ''), + ); + }, + sortable: true, + columnWidth: 250, + permission: 'AbpIdentity.Users.ReadSensitiveData', // hypothetical + visible: data => { + const store = data.getInjected(Store); + const selectSensitiveDataVisibility = ConfigState.getSetting( + 'Abp.Identity.IsSensitiveDataVisible' // hypothetical + ); + + return store.selectSnapshot(selectSensitiveDataVisibility).toLowerCase() === 'true'; + } +}; + +const prop = new EntityProp(options); +``` + +It also has two static methods to create its instances: + +- **EntityProp.create\\(options: EntityPropOptions\\)** is used to create an instance of `EntityProp`. + ```js + const prop = EntityProp.create(options); + ``` +- **EntityProp.createMany\\(options: EntityPropOptions\\[\]\)** is used to create multiple instances of `EntityProp` with given array of `EntityPropOptions`. + ```js + const props = EntityProp.createMany(optionsArray); + ``` + +### EntityPropList\ + +`EntityPropList` is the list of props passed to every prop contributor callback as the first parameter named `propList`. It is a **doubly linked list**. You may find [all available methods here](../Common/Utils/Linked-List.md). + +The items in the list will be displayed according to the linked list order, i.e. from head to tail. If you want to re-order them, all you have to do is something like this: + +```js +export function reorderUserContributors( + propList: EntityPropList, +) { + // drop email node + const emailPropNode = propList.dropByValue( + 'AbpIdentity::EmailAddress', + (prop, text) => prop.text === text, + ); + + // add it back after phoneNumber + propList.addAfter( + emailPropNode.value, + 'phoneNumber', + (value, name) => value.name === name, + ); +} +``` + +### EntityPropContributorCallback\ + +`EntityPropContributorCallback` is the type that you can pass as entity prop contributor callbacks to static `forLazy` methods of the modules. + +```js +export function isLockedOutPropContributor( + propList: EntityPropList, +) { + // add isLockedOutProp as 2nd column + propList.add(isLockedOutProp).byIndex(1); +} + +export const identityEntityPropContributors = { + [eIdentityComponents.Users]: [isLockedOutPropContributor], +}; +``` + +## See Also + +- [Customizing Application Modules Guide](../../Customizing-Application-Modules-Guide.md) diff --git a/docs/en/UI/Angular/Dynamic-Form-Extensions.md b/docs/en/UI/Angular/Dynamic-Form-Extensions.md new file mode 100644 index 0000000000..880250a247 --- /dev/null +++ b/docs/en/UI/Angular/Dynamic-Form-Extensions.md @@ -0,0 +1,325 @@ +# Dynamic Form (or Form Prop) Extensions for Angular UI + + +## Introduction + +Form prop extension system allows you to add a new field to the create and/or edit forms for a form or change/remove an already existing one. A "Date of Birth" field was added to the user management page below: + +![Form Prop Extension Example: "Date of Birth" Field](images/user-prop-extension-date-of-birth-field-ng.png) + +You can validate the field, perform visibility checks, and do more. You will also have access to the current entity when creating a contibutor for an edit form. + +## How to Set Up + +In this example, we will add a "Date of Birth" field in the user management page of the [Identity Module](../../Modules/Identity.md) and validate it. + +### Step 1. Create Form Prop Contributors + +The following code prepares two constants named `identityCreateFormPropContributors` and `identityEditFormPropContributors`, ready to be imported and used in your root module: + +```js +// form-prop-contributors.ts + +import { Validators } from '@angular/forms'; +import { ePropType, FormProp, FormPropList } from '@abp/ng.theme.shared/extensions'; +import { IdentityCreateFormPropContributors, IdentityEditFormPropContributors, IdentityUserDto } from '@volo/abp.ng.identity'; + +const birthdayProp = new FormProp({ + type: ePropType.Date, + name: 'birthday', + displayName: 'Date of Birth', + validators: () => [Validators.required], +}); + +export function birthdayPropContributor(propList: FormPropList) { + propList.addByIndex(birthdayProp, 4); +} + +export const identityCreateFormPropContributors: IdentityCreateFormPropContributors = { + 'Identity.UsersComponent': [birthdayPropContributor], +}; + +export const identityEditFormPropContributors: IdentityEditFormPropContributors = { + 'Identity.UsersComponent': [birthdayPropContributor], +}; + +``` + + +The list of props, conveniently named as `propList`, is a **doubly linked list**. That is why we have used the `addByIndex` method, which adds the given value to the specified index of the list. You may find [all available methods here](../Common/Utils/Linked-List.md). + +> **Important Note 1:** AoT compilation does not support function calls in decorator metadata. This is why we have defined `birthdayPropContributor` as an exported function declaration here. Please do not forget exporting your contributor callbacks and forget about lambda functions (a.k.a. arrow functions). Please refer to [AoT metadata errors](https://angular.io/guide/aot-metadata-errors#function-calls-not-supported) for details. + +> **Important Note 2:** Please use one of the following if Ivy is not enabled in your project. Otherwise, you will get an "Expression form not supported." error. + +```js +export const identityCreateFormPropContributors: IdentityCreateFormPropContributors = { + 'Identity.UsersComponent': [ birthdayPropContributor ], +}; + +/* OR */ + +const identityCreateContributors: IdentityCreateFormPropContributors = {}; +identityCreateContributors[eIdentityComponents.Users] = [ birthdayPropContributor ]; +export const identityCreateFormPropContributors = identityCreateContributors; +``` + +### Step 2. Import and Use Form Prop Contributors + +Import `identityCreateFormPropContributors` and `identityEditFormPropContributors` in your routing module and pass it to the static `forLazy` method of `IdentityModule` as seen below: + +```js +import { + identityCreateFormPropContributors, + identityEditFormPropContributors, +} from './form-prop-contributors'; + +const routes: Routes = [ + { + path: '', + component: DynamicLayoutComponent, + children: [ + { + path: 'identity', + loadChildren: () => + import('@volo/abp.ng.identity').then(m => + m.IdentityModule.forLazy({ + createFormPropContributors: identityCreateFormPropContributors, + editFormPropContributors: identityEditFormPropContributors, + }), + ), + }, + // other child routes + ], + // other routes + } +]; +``` + +That is it, `birthdayProp` form prop will be added, and you will see the datepicker for the "Date of Birth" field right before the "Email address" in the forms of the users page in the `IdentityModule`. + +## Object Extensions + +Extra properties defined on an existing entity will be included in the create and edit forms and validated based on their configuration. The form values will also be mapped to and from `extraProperties` automatically. They are available when defining custom contributors, so you can drop, modify, or reorder them. The `isExtra` identifier will be set to `true` for these properties and will define this automatic behavior. + +## API + +### PropData\ + +`PropData` is the shape of the parameter passed to all callbacks or predicates in a `FormProp`. + +It has the following properties: + +- **getInjected** is the equivalent of [Injector.get](https://angular.io/api/core/Injector#get). You can use it to reach injected dependencies of `ExtensibleFormPropComponent`, including, but not limited to, its parent components. + + ```js + { + type: ePropType.Enum, + name: 'myField', + options: data => { + const restService = data.getInjected(RestService); + const usersComponent = data.getInjected(UsersComponent); + + // Use restService and usersComponent public props and methods here + } + }, + ``` + +- **record** is the row data, i.e. current value of the selected item to edit. This property is _available only on edit forms_. + + ```js + { + type: ePropType.String, + name: 'myProp', + readonly: data => data.record.someOtherProp, + } + ``` + +### PropCallback\ + +`PropCallback` is the type of the callback function that can be passed to a `FormProp` as `prop` parameter. A prop callback gets a single parameter, the `PropData`. The return type may be anything, including `void`. Here is a simplified representation: + +```js +type PropCallback = (data?: PropData) => R; +``` + +### PropPredicate\ + +`PropPredicate` is the type of the predicate function that can be passed to a `FormProp` as `visible` parameter. A prop predicate gets a single parameter, the `PropData`. The return type must be `boolean`. Here is a simplified representation: + +```js +type PropPredicate = (data?: PropData) => boolean; +``` + +### FormPropOptions\ + +`FormPropOptions` is the type that defines required and optional properties you have to pass in order to create a form prop. + +Its type definition is as follows: + +```js +type FormPropOptions = { + type: ePropType; + name: string; + displayName?: string; + id?: string; + permission?: string; + visible?: PropPredicate; + readonly?: PropPredicate; + disabled?: PropPredicate; + validators?: PropCallback; + asyncValidators?: PropCallback; + defaultValue?: boolean | number | string | Date; + options?: PropCallback[]>>; + autocomplete?: string; + isExtra? boolean; +}; +``` + +As you see, passing `type` and `name` is enough to create a form prop. Here is what each property is good for: + +- **type** is the type of the prop value. It defines which input is rendered for the prop in the form. (_required_) +- **name** is the property name (or key) which will be used to read the value of the prop. (_required_) +- **displayName** is the name of the property which will be localized and shown as column header. (_default:_ `options.name`) +- **id** will be set as the `for` attribute of the label and the `id` attribute of the input for the field. (_default:_ `options.name`) +- **permission** is the permission context which will be used to decide if a column for this form prop should be displayed to the user or not. (_default:_ `undefined`) +- **visible** is a predicate that will be used to decide if this prop should be displayed on the form or not. (_default:_ `() => true`) +- **readonly** is a predicate that will be used to decide if this prop should be readonly or not. (_default:_ `() => false`) +- **disabled** is a predicate that will be used to decide if this prop should be disabled or not. (_default:_ `() => false`) +- **validators** is a callback that returns validators for the prop. (_default:_ `() => []`) +- **asyncValidators** is a callback that returns async validators for the prop. (_default:_ `() => []`) +- **defaultValue** is the initial value the field will have. (_default:_ `null`) +- **options** is a callback that is called when a dropdown is needed. It must return an observable. (_default:_ `undefined`) +- **autocomplete** will be set as the `autocomplete` attribute of the input for the field. Please check [possible values](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete#Values). (_default:_ `'off'`) +- **isExtra** indicates this prop is an object extension. When `true`, the value of the field will be mapped from and to `extraProperties` of the entity. (_default:_ `undefined`) + +> Important Note: Do not use `record` property of `PropData` in create form predicates and callbacks, because it will be `undefined`. You can use it on edit form contributors though. + +You may find a full example below. + +### FormProp\ + +`FormProp` is the class that defines your form props. It takes a `FormPropOptions` and sets the default values to the properties, creating a form prop that can be passed to a form contributor. + +```js +const options: FormPropOptions = { + type: ePropType.Enum, + name: 'myProp', + displayName: 'Default::MyPropName', + id: 'my-prop', + permission: 'AbpIdentity.Users.ReadSensitiveData', // hypothetical + visible: data => { + const store = data.getInjected(Store); + const selectSensitiveDataVisibility = ConfigState.getSetting( + 'Abp.Identity.IsSensitiveDataVisible' // hypothetical + ); + + return store.selectSnapshot(selectSensitiveDataVisibility).toLowerCase() === 'true'; + }, + readonly: data => data.record.someProp, + disabled: data => data.record.someOtherProp, + validators: () => [Validators.required], + asyncValidators: data => { + const http = data.getInjected(HttpClient); + + function validate(control: AbstractControl): Observable { + if (control.pristine) return of(null); + + return http + .get('https://api.my-brand.io/hypothetical/endpoint/' + control.value) + .pipe(map(response => (response.valid ? null : { invalid: true }))); + } + + return [validate]; + }, + defaultValue: 0, + options: data => { + const service = data.getInjected(MyIdentityService); + + return service.getMyPropOptions() + .pipe( + map(({items}) => items.map( + item => ({key: item.name, value: item.id }) + )), + ); + }, + autocomplete: 'off', + isExtra: true, +}; + +const prop = new FormProp(options); +``` + +It also has two static methods to create its instances: + +- **FormProp.create\\(options: FormPropOptions\\)** is used to create an instance of `FormProp`. + ```js + const prop = FormProp.create(options); + ``` +- **FormProp.createMany\\(options: FormPropOptions\\[\]\)** is used to create multiple instances of `FormProp` with given array of `FormPropOptions`. + ```js + const props = FormProp.createMany(optionsArray); + ``` + +### FormPropList\ + +`FormPropList` is the list of props passed to every prop contributor callback as the first parameter named `propList`. It is a **doubly linked list**. You may find [all available methods here](../Common/Utils/Linked-List.md). + +The items in the list will be displayed according to the linked list order, i.e. from head to tail. If you want to re-order them, all you have to do is something like this: + +```js +export function reorderUserContributors( + propList: FormPropList, +) { + // drop email node + const emailPropNode = propList.dropByValue( + 'AbpIdentity::EmailAddress', + (prop, displayName) => prop.displayName === displayName, + ); + + // add it back after phoneNumber + propList.addAfter( + emailPropNode.value, + 'phoneNumber', + (value, name) => value.name === name, + ); +} +``` + +### CreateFormPropContributorCallback\ + +`CreateFormPropContributorCallback` is the type that you can pass as **create form** prop contributor callbacks to static `forLazy` methods of the modules. + +```js +export function myPropCreateContributor( + propList: FormPropList, +) { + // add myProp as 2nd field from the start + propList.add(myProp).byIndex(1); +} + +export const identityCreateFormPropContributors = { + [eIdentityComponents.Users]: [myPropCreateContributor], +}; +``` + +### EditFormPropContributorCallback\ + +`EditFormPropContributorCallback` is the type that you can pass as **edit form** prop contributor callbacks to static `forLazy` methods of the modules. + +```js +export function myPropEditContributor( + propList: FormPropList, +) { + // add myProp as 2nd field from the end + propList.add(myProp).byIndex(-1); +} + +export const identityEditFormPropContributors = { + [eIdentityComponents.Users]: [myPropEditContributor], +}; +``` + +## See Also + +- [Customizing Application Modules Guide](../../Customizing-Application-Modules-Guide.md) diff --git a/docs/en/UI/Angular/Entity-Action-Extensions.md b/docs/en/UI/Angular/Entity-Action-Extensions.md new file mode 100644 index 0000000000..d46bd8e194 --- /dev/null +++ b/docs/en/UI/Angular/Entity-Action-Extensions.md @@ -0,0 +1,442 @@ +# Entity Action Extensions for Angular UI + +## Introduction + +Entity action extension system allows you to add a new action to the action menu for an entity. A "Click Me" action was added to the user management page below: + +![Entity Action Extension Example: "Click Me!" Action](images/user-action-extension-click-me-ng.png) + +You can take any action (open a modal, make an HTTP API call, redirect to another page... etc) by writing your custom code. You can access to the current entity in your code. + +## How to Set Up + +In this example, we will add a "Click Me!" action and alert the current row's `userName` in the user management page of the [Identity Module](../../Modules/Identity.md). + +### Step 1. Create Entity Action Contributors + +The following code prepares a constant named `identityEntityActionContributors`, ready to be imported and used in your root module: + +```js +// entity-action-contributors.ts + +import { EntityAction, EntityActionList } from '@abp/ng.theme.shared/extensions'; +import { IdentityEntityActionContributors, IdentityUserDto } from '@volo/abp.ng.identity'; + +const alertUserName = new EntityAction({ + text: 'Click Me!', + action: data => { + // Replace alert with your custom code + alert(data.record.userName); + }, + // See EntityActionOptions in API section for all options +}); + +export function alertUserNameContributor( + actionList: EntityActionList, +) { + actionList.addTail(alertUserName); +} + +export const identityEntityActionContributors: IdentityEntityActionContributors = { + // enum indicates the page to add contributors to + [eIdentityComponents.Users]: [ + alertUserNameContributor, + // You can add more contributors here + ], +}; +``` + +The list of actions, conveniently named as `actionList`, is a **doubly linked list**. That is why we have used the `addTail` method, which adds the given value to the end of the list. You may find [all available methods here](../Common/Utils/Linked-List.md). + +> **Important Note 1:** AoT compilation does not support function calls in decorator metadata. This is why we have defined `alertUserNameContributor` as an exported function declaration here. Please do not forget exporting your contributor callbacks and forget about lambda functions (a.k.a. arrow functions). Please refer to [AoT metadata errors](https://angular.io/guide/aot-metadata-errors#function-calls-not-supported) for details. + +> **Important Note 2:** Please use one of the following if Ivy is not enabled in your project. Otherwise, you will get an "Expression form not supported." error. + +```js +export const identityEntityActionContributors: IdentityEntityActionContributors = { + 'Identity.UsersComponent': [ alertUserNameContributor ], +}; + +/* OR */ + +const identityContributors: IdentityEntityActionContributors = {}; +identityContributors[eIdentityComponents.Users] = [ alertUserNameContributor ]; +export const identityEntityActionContributors = identityContributors; +``` + +### Step 2. Import and Use Entity Action Contributors + +Import `identityEntityActionContributors` in your routing module and pass it to the static `forLazy` method of `IdentityModule` as seen below: + +```js +import { identityEntityActionContributors } from './entity-action-contributors'; + +const routes: Routes = [ + { + path: '', + component: DynamicLayoutComponent, + children: [ + { + path: 'identity', + loadChildren: () => + import('@volo/abp.ng.identity').then(m => + m.IdentityModule.forLazy({ + entityActionContributors: identityEntityActionContributors, + }), + ), + }, + // other child routes + ], + // other routes + } +]; +``` + +That is it, `alertUserName` entity action will be added as the last action on the grid dropdown in the users page (`UsersComponent`) of the `IdentityModule`. + +## How to Place a Custom Modal and Trigger It by Entity Actions + +Incase you need to place a custom modal that will be triggered by an entity action, there are two ways to do it: A quick one and an elaborate one. + +### The Quick Solution + +1. Place your custom modal inside `AppComponent` template. + ```html + + +

+
+ + + + + + + + + + +
+ ``` + +2. Add the following inside your `AppComponent` class: + ```js + isModalOpen: boolean; + + openModal(/* may take parameters */) { + /* and set things before showing the modal */ + this.isModalOpen = true; + } + ``` + +3. Add an entity action similar to this: + ```js + const customModalAction = new EntityAction({ + text: 'Custom Modal Action', + action: data => { + const component = data.getInjected(AppComponent); + component.openModal(/* you may pass parameters */); + }, + }); + ``` + +That should work. However, there is a longer but lazy-loading solution, and we are going to use NGXS for it. + +### The Elaborate Solution + +Consider the modal will be displayed in the Identity module. How can we lazy-load it too? + +1. Create a folder called `identity-extended` inside your app folder. +2. Create a file called `identity-popups.store.ts` in it. +3. Insert the following code in the new file: + ```js + import { Action, Selector, State, StateContext } from '@ngxs/store'; + + export class ToggleIdentityPopup { + static readonly type = '[IdentityPopups] Toggle'; + constructor(public readonly payload: boolean) {} + } + + @State({ + name: 'IdentityPopups', + defaults: { + isVisible: false, + }, + }) + export class IdentityPopupsState { + @Selector() + static isVisible(state: IdentityPopupsStateModel) { + return state.isVisible; + } + + @Action(ToggleIdentityPopup) + toggleModal( + context: StateContext, + { payload }: ToggleIdentityPopup, + ) { + context.patchState({ isVisible: payload }); + } + } + + interface IdentityPopupsStateModel { + isVisible: boolean; + } + ``` + +4. Create a file called `identity-extended.module.ts` in the same folder. +5. Insert the following code in the new file: + ```js + import { CoreModule } from '@abp/ng.core'; + import { ThemeSharedModule } from '@abp/ng.theme.shared'; + import { Component, NgModule } from '@angular/core'; + import { RouterModule } from '@angular/router'; + import { NgxsModule, Select, Store } from '@ngxs/store'; + import { Observable } from 'rxjs'; + import { IdentityPopupsState, ToggleIdentityPopup } from './identity-popups.store'; + + @Component({ + template: ` + + + `, + }) + export class IdentityOutletComponent {} + + @Component({ + template: ` + + +

+
+ + + + + + + + + + +
+ `, + }) + export class IdentityPopupsComponent { + @Select(IdentityPopupsState.isVisible) + isVisible$: Observable; + + constructor(private store: Store) {} + + onDisappear() { + this.store.dispatch(new ToggleIdentityPopup(false)); + } + } + + @NgModule({ + declarations: [IdentityPopupsComponent, IdentityOutletComponent], + imports: [ + CoreModule, + ThemeSharedModule, + NgxsModule.forFeature([IdentityPopupsState]), + RouterModule.forChild([ + { + path: '', + component: IdentityOutletComponent, + children: [ + { + path: '', + outlet: 'popup', + component: IdentityPopupsComponent, + }, + { + path: '', + loadChildren: () => import('@volo/abp.ng.identity').then(m => m.IdentityModule), + }, + ], + }, + ]), + ], + }) + export class IdentityExtendedModule {} + ``` + +6. Change the `identity` path in your `AppRoutingModule` to this: + ```js + { + path: 'identity', + loadChildren: () => + import('./identity-extended/identity-extended.module').then(m => m.IdentityExtendedModule), + }, + ``` + +7. Add an entity action similar to this: + ```js + const customModalAction = new EntityAction({ + text: 'Custom Modal Action', + action: data => { + const store = data.getInjected(Store); + store.dispatch(new ToggleIdentityPopup(true)); + }, + }); + ``` + +It should now be working well with lazy-loading. The files are compact in the description to make it quicker to explain. You may split the files as you wish. + +## API + +### ActionData\ + +`ActionData` is the shape of the parameter passed to all callbacks or predicates in an `EntityAction`. + +It has the following properties: + +- **record** is the row data, i.e. current value rendered in the table. + + ```js + { + text: 'Click Me!', + action: data => { + alert(data.record.userName); + }, + } + ``` + +- **index** is the table index where the record is at. + +- **getInjected** is the equivalent of [Injector.get](https://angular.io/api/core/Injector#get). You can use it to reach injected dependencies of `GridActionsComponent`, including, but not limited to, its parent component. + + ```js + { + text: 'Click Me!', + action: data => { + const restService = data.getInjected(RestService); + + // Use restService public props and methods here + }, + visible: data => { + const usersComponent = data.getInjected(UsersComponent); + + // Use usersComponent public props and methods here + }, + } + ``` + +### ActionCallback\ + +`ActionCallback` is the type of the callback function that can be passed to an `EntityAction` as `action` parameter. An action callback gets a single parameter, the `ActionData`. The return type may be anything, including `void`. Here is a simplified representation: + +```js +type ActionCallback = (data?: ActionData) => R; +``` + +### ActionPredicate\ + +`ActionPredicate` is the type of the predicate function that can be passed to an `EntityAction` as `visible` parameter. An action predicate gets a single parameter, the `ActionData`. The return type must be `boolean`. Here is a simplified representation: + +```js +type ActionPredicate = (data?: ActionData) => boolean; +``` + +### EntityActionOptions\ + +`EntityActionOptions` is the type that defines required and optional properties you have to pass in order to create an entity action. + +Its type definition is as follows: + +```js +type EntityActionOptions = { + action: ActionCallback, + text: string, + icon?: string, + permission?: string, + visible?: ActionPredicate, +}; +``` + +As you see, passing `action` and `text` is enough to create an entity action. Here is what each property is good for: + +- **action** is a callback that is called when the grid action is clicked. (_required_) +- **text** is the button text which will be localized. (_required_) +- **icon** is the classes that define an icon to be placed before the text. (_default:_ `''`) +- **permission** is the permission context which will be used to decide if this type of grid action should be displayed to the user or not. (_default:_ `undefined`) +- **visible** is a predicate that will be used to decide if the current record should have this grid action or not. (_default:_ `() => true`) + +You may find a full example below. + +### EntityAction\ + +`EntityAction` is the class that defines your entity actions. It takes an `EntityActionOptions` and sets the default values to the properties, creating an entity action that can be passed to an entity contributor. + +```js +const options: EntityActionOptions = { + action: data => { + const component = data.getInjected(UsersComponent); + component.unlock(data.record.id); + }, + text: 'AbpIdentity::Unlock', + icon: 'fa fa-unlock', + permission: 'AbpIdentity.Users.Update', + visible: data => data.record.isLockedOut, +}; + +const action = new EntityAction(options); +``` + +It also has two static methods to create its instances: + +- **EntityAction.create\\(options: EntityActionOptions\\)** is used to create an instance of `EntityAction`. + ```js + const action = EntityAction.create(options); + ``` +- **EntityAction.createMany\\(options: EntityActionOptions\\[\]\)** is used to create multiple instances of `EntityAction` with given array of `EntityActionOptions`. + ```js + const actions = EntityAction.createMany(optionsArray); + ``` + +### EntityActionList\ + +`EntityActionList` is the list of actions passed to every action contributor callback as the first parameter named `actionList`. It is a **doubly linked list**. You may find [all available methods here](../Common/Utils/Linked-List.md). + +The items in the list will be displayed according to the linked list order, i.e. from head to tail. If you want to re-order them, all you have to do is something like this: + +```js +export function reorderUserContributors( + actionList: EntityActionList, +) { + // drop "Unlock" button + const unlockActionNode = actionList.dropByValue( + 'AbpIdentity::Unlock', + (action, text) => action.text === text, + ); + + // add it back to the head of the list + actionList.addHead(unlockActionNode.value); +} +``` + +### EntityActionContributorCallback\ + +`EntityActionContributorCallback` is the type that you can pass as entity action contributor callbacks to static `forLazy` methods of the modules. + +```js +// lockUserContributor should have EntityActionContributorCallback type + +export function lockUserContributor( + actionList: EntityActionList, +) { + // add lockUser as 3rd action + actionList.add(lockUser).byIndex(2); +} + +export const identityEntityActionContributors = { + [eIdentityComponents.Users]: [lockUserContributor], +}; +``` + +## See Also + +- [Customizing Application Modules Guide](../../Customizing-Application-Modules-Guide.md) diff --git a/docs/en/UI/Angular/Form-Validation.md b/docs/en/UI/Angular/Form-Validation.md index 38e7969eea..a178fa213c 100644 --- a/docs/en/UI/Angular/Form-Validation.md +++ b/docs/en/UI/Angular/Form-Validation.md @@ -6,23 +6,52 @@ Reactive forms in ABP Angular UI are validated by [ngx-validate](https://www.npm ## How to Add New Error Messages -You can add a new error message by providing the `VALIDATION_BLUEPRINTS` injection token from your root module. +You can add a new error message by passing validation options to the `ThemeSharedModule` in your root module. ```js import { VALIDATION_BLUEPRINTS } from "@ngx-validate/core"; +import { DEFAULT_VALIDATION_BLUEPRINTS } from "@abp/ng.theme.shared"; @NgModule({ + imports: [ + ThemeSharedModule.forRoot({ + validation: { + blueprints: { + uniqueUsername: "::AlreadyExists[{%{{{ username }}}%}]", + }, + }, + + // rest of theme shared config + }), + + // other imports + ], + // rest of the module metadata +}) +export class AppModule {} +``` + +Alternatively, you may provide the `VALIDATION_BLUEPRINTS` token directly in your root module. Please do not forget to spread `DEFAULT_VALIDATION_BLUEPRINTS`. Otherwise, built-in ABP validation messages will not work. +```js +import { VALIDATION_BLUEPRINTS } from "@ngx-validate/core"; +import { DEFAULT_VALIDATION_BLUEPRINTS } from "@abp/ng.theme.shared"; + +@NgModule({ providers: [ - // other providers { provide: VALIDATION_BLUEPRINTS, useValue: { + ...DEFAULT_VALIDATION_BLUEPRINTS, uniqueUsername: "::AlreadyExists[{%{{{ username }}}%}]", }, }, + + // other providers ], + + // rest of the module metadata }) export class AppModule {} ``` @@ -40,7 +69,7 @@ In this example; ## How to Change Existing Error Messages -You can overwrite an existing error message by providing `VALIDATION_BLUEPRINTS` injection token from your root module. Let's imagine you have a custom localization resource for required inputs. +You can overwrite an existing error message by passing validation options to the `ThemeSharedModule` in your root module. Let's imagine you have a custom localization resource for required inputs. ```json "RequiredInput": "Oops! We need this input." @@ -50,19 +79,48 @@ To use this instead of the built-in required input message, all you need to do i ```js import { VALIDATION_BLUEPRINTS } from "@ngx-validate/core"; +import { DEFAULT_VALIDATION_BLUEPRINTS } from "@abp/ng.theme.shared"; @NgModule({ + imports: [ + ThemeSharedModule.forRoot({ + validation: { + blueprints: { + required: "::RequiredInput", + }, + }, + + // rest of theme shared config + }), + + // other imports + ], + // rest of the module metadata +}) +export class AppModule {} +``` + +Alternatively, you may provide the `VALIDATION_BLUEPRINTS` token directly in your root module. Please do not forget to spread `DEFAULT_VALIDATION_BLUEPRINTS`. Otherwise, built-in ABP validation messages will not work. +```js +import { VALIDATION_BLUEPRINTS } from "@ngx-validate/core"; +import { DEFAULT_VALIDATION_BLUEPRINTS } from "@abp/ng.theme.shared"; + +@NgModule({ providers: [ - // other providers { provide: VALIDATION_BLUEPRINTS, useValue: { + ...DEFAULT_VALIDATION_BLUEPRINTS, required: "::RequiredInput", }, }, + + // other providers ], + + // rest of the module metadata }) export class AppModule {} ``` diff --git a/docs/en/UI/Angular/Page-Toolbar-Extensions.md b/docs/en/UI/Angular/Page-Toolbar-Extensions.md new file mode 100644 index 0000000000..187ac9387d --- /dev/null +++ b/docs/en/UI/Angular/Page-Toolbar-Extensions.md @@ -0,0 +1,420 @@ +# Page Toolbar Extensions for Angular UI + +## Introduction + +Page toolbar extension system allows you to add a new action to the toolbar of a page. A "Click Me" action was added to the user management page below: + +![Page Toolbar Extension Example: "Click Me!" Action](images/user-page-toolbar-extension-click-me-ng.png) + +You can take any action (open a modal, make an HTTP API call, redirect to another page... etc) by writing your custom code. You can also access to page data (the main record, usually an entity list) in your code. Additionally, you can pass in custom components instead of using the default button. + +## How to Add an Action to Page Toolbar + +In this example, we will add a "Click Me!" action and log `userName` of all users in the user management page of the [Identity Module](../../Modules/Identity.md) to the console. + +### Step 1. Create Toolbar Action Contributors + +The following code prepares a constant named `identityToolbarActionContributors`, ready to be imported and used in your root module: + +```js +// toolbar-action-contributors.ts + +import { ToolbarActionList, ToolbarAction } from '@abp/ng.theme.shared/extensions'; +import { IdentityToolbarActionContributors, IdentityUserDto } from '@volo/abp.ng.identity'; + +const logUserNames = new ToolbarAction({ + text: 'Click Me!', + action: data => { + // Replace log with your custom code + data.record.forEach(user => console.log(user.userName)); + }, + // See ToolbarActionOptions in API section for all options +}); + +export function logUserNamesContributor( + actionList: ToolbarActionList +) { + actionList.addHead(logUserNames); +} + +export const identityToolbarActionContributors: IdentityToolbarActionContributors = { + // enum indicates the page to add contributors to + [eIdentityComponents.Users]: [ + logUserNamesContributor, + // You can add more contributors here + ], +}; + +``` + +The list of actions, conveniently named as `actionList`, is a **doubly linked list**. That is why we have used the `addHead` method, which adds the given value to the beginning of the list. You may find [all available methods here](../Common/Utils/Linked-List.md). + +> **Important Note:** AoT compilation does not support function calls in decorator metadata. This is why we have defined `logUserNamesContributor` as an exported function declaration here. Please do not forget exporting your contributor callbacks and forget about lambda functions (a.k.a. arrow functions). Please refer to [AoT metadata errors](https://angular.io/guide/aot-metadata-errors#function-calls-not-supported) for details. + +### Step 2. Import and Use Toolbar Action Contributors + +Import `identityToolbarActionContributors` in your routing module and pass it to the static `forLazy` method of `IdentityModule` as seen below: + +```js +import { identityToolbarActionContributors } from './toolbar-action-contributors'; + +const routes: Routes = [ + { + path: '', + component: DynamicLayoutComponent, + children: [ + { + path: 'identity', + loadChildren: () => + import('@volo/abp.ng.identity').then(m => + m.IdentityModule.forLazy({ + toolbarActionContributors: identityToolbarActionContributors, + }), + ), + }, + // other child routes + ], + // other routes + } +]; +``` + +That is it, `logUserNames` toolbar action will be added as the first action on the page toolbar in the users page (`UsersComponent`) of the `IdentityModule`. + +## How to Add a Custom Component to Page Toolbar + +In this example, we will add a custom "Click Me!" button and log `userName` of all users in the user management page of the [Identity Module](../../Modules/Identity.md) to the console. + +### Step 1. Create A Custom Component + +We need to have a component before we can pass it to the toolbar action contributors: + +```js +// click-me-button.component.ts + +import { Component, Inject } from '@angular/core'; +import { ActionData, EXTENSIONS_ACTION_DATA } from '@abp/ng.theme.shared/extensions'; +import { IdentityUserDto } from '@volo/abp.ng.identity'; + +@Component({ + selector: 'app-click-me-button', + template: ` + + `, +}) +export class ClickMeButtonComponent { + constructor( + @Inject(EXTENSIONS_ACTION_DATA) + private data: ActionData + ) {} + + handleClick() { + this.data.record.forEach(user => console.log(user.userName)); + } +} +``` + +Here, `EXTENSIONS_ACTION_DATA` token provides us the context from the page toolbar. Therefore, we are able to reach the page data via `record`, which is an array of users, i.e. `IdentityUserDto[]`. + +> We could also import `EXTENSIONS_ACTION_CALLBACK` from **@abp/ng.theme.shared/extensions** package, which is a higher order function that triggers the predefined `action` when called. It passes `ActionData` as the first parameter, so you do not have to pass it explicitly. In other words, `EXTENSIONS_ACTION_CALLBACK` can be called without any parameters and it will not fail. + +### Step 2. Create Toolbar Action Contributors + +The following code prepares a constant named `identityToolbarActionContributors`, ready to be imported and used in your root module. When `ToolbarComponent` is used instead of `ToolbarAction`, we can pass a component in: + +```js +// toolbar-action-contributors.ts + +import { ToolbarActionList, ToolbarComponent } from '@abp/ng.theme.shared/extensions'; +import { IdentityUserDto } from '@volo/abp.ng.identity'; +import { IdentityToolbarActionContributors } from '@volo/abp.ng.identity/config'; +import { ClickMeButtonComponent } from './click-me-button.component'; + +const logUserNames = new ToolbarComponent({ + component: ClickMeButtonComponent, + // See ToolbarActionOptions in API section for all options +}); + +export function logUserNamesContributor( + actionList: ToolbarActionList +) { + actionList.addHead(logUserNames); +} + +export const identityToolbarActionContributors: IdentityToolbarActionContributors = { + // enum indicates the page to add contributors to + [eIdentityComponents.Users]: [ + logUserNamesContributor, + // You can add more contributors here + ], +}; + +``` + +The list of actions, conveniently named as `actionList`, is a **doubly linked list**. That is why we have used the `addHead` method, which adds the given value to the beginning of the list. You may find [all available methods here](../Common/Utils/Linked-List.md). + +> **Important Note 1:** AoT compilation does not support function calls in decorator metadata. This is why we have defined `logUserNamesContributor` as an exported function declaration here. Please do not forget exporting your contributor callbacks and forget about lambda functions (a.k.a. arrow functions). Please refer to [AoT metadata errors](https://angular.io/guide/aot-metadata-errors#function-calls-not-supported) for details. + +> **Important Note 2:** Please use one of the following if Ivy is not enabled in your project. Otherwise, you will get an "Expression form not supported." error. + +```js +export const identityToolbarActionContributors: IdentityToolbarActionContributors = { + 'Identity.UsersComponent': [ logUserNamesContributor ], +}; + +/* OR */ + +const identityContributors: IdentityToolbarActionContributors = {}; +identityContributors[eIdentityComponents.Users] = [ logUserNamesContributor ]; +export const identityToolbarActionContributors = identityContributors; +``` + +### Step 3. Import and Use Toolbar Action Contributors + +Import `identityToolbarActionContributors` in your routing module and pass it to the static `forLazy` method of `IdentityModule` as seen below. If Ivy is not enabled in your project, do not forget putting `ClickMeButtonComponent` into `entryComponents`: + +```js +import { identityToolbarActionContributors } from './toolbar-action-contributors'; + +const routes: Routes = [ + { + path: '', + component: DynamicLayoutComponent, + children: [ + { + path: 'identity', + loadChildren: () => + import('@volo/abp.ng.identity').then(m => + m.IdentityModule.forLazy({ + toolbarActionContributors: identityToolbarActionContributors, + }), + ), + }, + // other child routes + ], + // other routes + } +]; +``` + +That is it, `logUserNames` toolbar action will be added as the first action on the page toolbar in the users page (`UsersComponent`) of the `IdentityModule` and it will be triggered by a custom button, i.e. `ClickMeButtonComponent`. Please note that **component projection is not limited to buttons** and you may use other UI components. + +![Page Toolbar Extension Example: Custom "Click Me!" Button](images/user-page-toolbar-extension-custom-click-me-ng.png) + +## How to Place a Custom Modal and Trigger It by Toolbar Actions + +Please check the same topic in [entity action extensions document](Entity-Action-Extensions.md) and replace entity action with a toolbar action. + +## API + +### ActionData\ + +`ActionData` is the shape of the parameter passed to all callbacks or predicates in a `ToolbarAction`. + +It has the following properties: + +- **record** is the page data, the main record on a page, usually an entity list (e.g. list of users). + + ```js + { + text: 'Click Me!', + action: data => { + data.record.forEach(user => { + console.lof(user.userName); + }); + }, + } + ``` + +- **getInjected** is the equivalent of [Injector.get](https://angular.io/api/core/Injector#get). You can use it to reach injected dependencies of `PageToolbarComponent`, including, but not limited to, its parent component. + + ```js + { + text: 'Click Me!', + action: data => { + const restService = data.getInjected(RestService); + + // Use restService public props and methods here + }, + visible: data => { + const usersComponent = data.getInjected(UsersComponent); + + // Use usersComponent public props and methods here + }, + } + ``` + +### ActionCallback\ + +`ActionCallback` is the type of the callback function that can be passed to a `ToolbarAction` as `action` parameter. An action callback gets a single parameter, the `ActionData`. The return type may be anything, including `void`. Here is a simplified representation: + +```js +type ActionCallback = (data?: ActionData) => R; +``` + +### ActionPredicate\ + +`ActionPredicate` is the type of the predicate function that can be passed to a `ToolbarAction` as `visible` parameter. An action predicate gets a single parameter, the `ActionData`. The return type must be `boolean`. Here is a simplified representation: + +```js +type ActionPredicate = (data?: ActionData) => boolean; +``` + +### ToolbarActionOptions\ + +`ToolbarActionOptions` is the type that defines required and optional properties you have to pass in order to create an toolbar action. + +Its type definition is as follows: + +```js +type ToolbarActionOptions = { + action: ActionCallback, + text: string, + icon?: string, + permission?: string, + visible?: ActionPredicate, +}; +``` + +As you see, passing `action` and `text` is enough to create an toolbar action. Here is what each property is good for: + +- **action** is a callback that is called when the toolbar action is clicked. (_required_) +- **text** is the button text which will be localized. (_required_) +- **icon** is the classes that define an icon to be placed before the text. (_default:_ `''`) +- **permission** is the permission context which will be used to decide if this toolbar action should be displayed to the user or not. (_default:_ `undefined`) +- **visible** is a predicate that will be used to decide if the page toolbar should have this action or not. (_default:_ `() => true`) + +You may find a full example below. + +### ToolbarAction\ + +`ToolbarAction` is the class that defines your toolbar actions. It takes an `ToolbarActionOptions` and sets the default values to the properties, creating an toolbar action that can be passed to an toolbar contributor. + +```js +const options: ToolbarActionOptions = { + action: data => { + const service = data.getInjected(MyCustomIdentityService); + const lockedUsers = data.record.filter(user => user.isLockedOut); + service.unlockAll(lockedUsers); + }, + text: 'MyProjectName::UnlockAll', + icon: 'fa fa-unlock', + permission: 'AbpIdentity.Users.Update', + visible: data => data.record.some(user => user.isLockedOut), +}; + +const action = new ToolbarAction(options); +``` + +It also has two static methods to create its instances: + +- **ToolbarAction.create\\(options: ToolbarActionOptions\\)** is used to create an instance of `ToolbarAction`. + ```js + const action = ToolbarAction.create(options); + ``` +- **ToolbarAction.createMany\\(options: ToolbarActionOptions\\[\]\)** is used to create multiple instances of `ToolbarAction` with given array of `ToolbarActionOptions`. + +### ToolbarComponentOptions\ + +`ToolbarComponentOptions` is the type that defines required and optional properties you have to pass in order to create an toolbar component. + +Its type definition is as follows: + +```js +type ToolbarComponentOptions = { + component: Type, + action?: ActionCallback, + permission?: string, + visible?: ActionPredicate, +}; +``` + +As you see, passing `action` and `text` is enough to create an toolbar action. Here is what each property is good for: + +- **component** is the constructor of the component to be projected. (_required_) +- **action** is a predefined callback that you can reach in your component via `EXTENSIONS_ACTION_CALLBACK` token and trigger. (_optional_) +- **permission** is the permission context which will be used to decide if this toolbar action should be displayed to the user or not. (_default:_ `undefined`) +- **visible** is a predicate that will be used to decide if the page toolbar should have this action or not. (_default:_ `() => true`) + +You may find a full example below. + +### ToolbarComponent\ + +`ToolbarComponent` is the class that defines toolbar actions which project a custom component. It takes an `ToolbarComponentOptions` and sets the default values to the properties, creating a toolbar action that can be passed to an toolbar contributor. + +```js +const options: ToolbarComponentOptions = { + component: UnlockAllButton, + action: data => { + const service = data.getInjected(MyCustomIdentityService); + const lockedUsers = data.record.filter(user => user.isLockedOut); + service.unlockAll(lockedUsers); + }, + permission: 'AbpIdentity.Users.Update', + visible: data => data.record.some(user => user.isLockedOut), +}; + +const action = new ToolbarComponent(options); +``` + +It also has two static methods to create its instances: + +- **ToolbarComponent.create\\(options: ToolbarComponentOptions\\)** is used to create an instance of `ToolbarComponent`. + ```js + const action = ToolbarComponent.create(options); + ``` +- **ToolbarComponent.createMany\\(options: ToolbarComponentOptions\\[\]\)** is used to create multiple instances of `ToolbarComponent` with given array of `ToolbarComponentOptions`. + ```js + const actions = ToolbarComponent.createMany(optionsArray); + ``` + +### ToolbarActionList\ + +`ToolbarActionList` is the list of actions passed to every action contributor callback as the first parameter named `actionList`. It is a **doubly linked list**. You may find [all available methods here](../Common/Utils/Linked-List.md). + +The items in the list will be displayed according to the linked list order, i.e. from head to tail. If you want to re-order them, all you have to do is something like this: + +```js +export function reorderUserContributors( + actionList: ToolbarActionList, +) { + // drop "New User" button + const newUserActionNode = actionList.dropByValue( + 'AbpIdentity::NewUser', + (action, text) => action['text'] === text, + ); + + // add it back to the head of the list + actionList.addHead(newUserActionNode.value); +} + +export const identityEntityActionContributors = { + [eIdentityComponents.Users]: [ + logUserNamesContributor, + reorderUserContributors, + ], +}; +``` + +### ToolbarActionContributorCallback\ + +`ToolbarActionContributorCallback` is the type that you can pass as toolbar action contributor callbacks to static `forLazy` methods of the modules. + +```js +// exportUsersContributor should have ToolbarActionContributorCallback type + +export function exportUsersContributor( + actionList: ToolbarActionList, +) { + // add exportUsers just before the last action + actionList.add(exportUsers).byIndex(-1); +} + +export const identityEntityActionContributors = { + [eIdentityComponents.Users]: [exportUsersContributor], +}; +``` + +## See Also + +- [Customizing Application Modules Guide](../../Customizing-Application-Modules-Guide.md) diff --git a/docs/en/UI/Angular/images/user-action-extension-click-me-ng.png b/docs/en/UI/Angular/images/user-action-extension-click-me-ng.png new file mode 100644 index 0000000000..675f05217a Binary files /dev/null and b/docs/en/UI/Angular/images/user-action-extension-click-me-ng.png differ diff --git a/docs/en/UI/Angular/images/user-page-toolbar-extension-click-me-ng.png b/docs/en/UI/Angular/images/user-page-toolbar-extension-click-me-ng.png new file mode 100644 index 0000000000..fcd36e4a7b Binary files /dev/null and b/docs/en/UI/Angular/images/user-page-toolbar-extension-click-me-ng.png differ diff --git a/docs/en/UI/Angular/images/user-page-toolbar-extension-custom-click-me-ng.png b/docs/en/UI/Angular/images/user-page-toolbar-extension-custom-click-me-ng.png new file mode 100644 index 0000000000..d8fd054eda Binary files /dev/null and b/docs/en/UI/Angular/images/user-page-toolbar-extension-custom-click-me-ng.png differ diff --git a/docs/en/UI/Angular/images/user-prop-extension-date-of-birth-field-ng.png b/docs/en/UI/Angular/images/user-prop-extension-date-of-birth-field-ng.png new file mode 100644 index 0000000000..948c4a9fd5 Binary files /dev/null and b/docs/en/UI/Angular/images/user-prop-extension-date-of-birth-field-ng.png differ diff --git a/docs/en/UI/Angular/images/user-prop-extension-name-column-ng.png b/docs/en/UI/Angular/images/user-prop-extension-name-column-ng.png new file mode 100644 index 0000000000..82d72b40ec Binary files /dev/null and b/docs/en/UI/Angular/images/user-prop-extension-name-column-ng.png differ diff --git a/docs/en/UI/AspNetCore/Page-Toolbar-Extensions.md b/docs/en/UI/AspNetCore/Page-Toolbar-Extensions.md new file mode 100644 index 0000000000..db466bebdb --- /dev/null +++ b/docs/en/UI/AspNetCore/Page-Toolbar-Extensions.md @@ -0,0 +1,163 @@ +# Page Toolbar Extensions for ASP.NET Core UI + +Page toolbar system allows you to add components to the toolbar of any page. The page toolbar is the area right to the header of a page. A button ("Import users from excel") was added to the user management page below: + +![page-toolbar-button](../../images/page-toolbar-button.png) + +You can add any type of view component item to the page toolbar or modify existing items. + +## How to Set Up + +In this example, we will add an "Import users from excel" button and execute a JavaScript code for the user management page of the [Identity Module](../../Modules/Identity.md). + +### Add a New Button to the User Management Page + +Write the following code inside the `ConfigureServices` of your web module class: + +````csharp +Configure(options => +{ + options.Configure(toolbar => + { + toolbar.AddButton( + LocalizableString.Create("ImportFromExcel"), + icon: "file-import", + id: "ImportUsersFromExcel", + type: AbpButtonType.Secondary + ); + }); +}); +```` + +`AddButton` is a shortcut to simply add a button component. Note that you need to add the `ImportFromExcel` to your localization dictionary (json file) to localize the text. + +When you run the application, you will see the button added next to the current button list. There are some other parameters of the `AddButton` method (for example, use `order` to set the order of the button component relative to the other components). + +### Create a JavaScript File + +Now, we can go to the client side to handle click event of the new button. First, add a new JavaScript file to your solution. We added inside the `/Pages/Identity/Users` folder of the `.Web` project: + +![user-action-extension-on-solution](../../images/user-action-extension-on-solution.png) + +Here, the content of this JavaScript file: + +````js +$(function () { + $('#ImportUsersFromExcel').click(function (e) { + e.preventDefault(); + alert('TODO: import users from excel'); + }); +}); +```` + +In the `click` event, you can do anything you need to do. + +### Add the File to the User Management Page + +Then you need to add this JavaScript file to the user management page. You can take the power of the [Bundling & Minification system](Bundling-Minification.md). + +Write the following code inside the `ConfigureServices` of your module class: + +````csharp +Configure(options => +{ + options.ScriptBundles.Configure( + typeof(Volo.Abp.Identity.Web.Pages.Identity.Users.IndexModel).FullName, + bundleConfiguration => + { + bundleConfiguration.AddFiles( + "/Pages/Identity/Users/my-user-extensions.js" + ); + }); +}); +```` + +This configuration adds `my-user-extensions.js` to the user management page of the Identity Module. `typeof(Volo.Abp.Identity.Web.Pages.Identity.Users.IndexModel).FullName` is the name of the bundle in the user management page. This is a common convention used for all the ABP Commercial modules. + +## Advanced Use Cases + +While you typically want to add a button action to the page toolbar, it is possible to add any type of component. + +### Add View Component to a Page Toolbar + +First, create a new view component in your project: + +![page-toolbar-custom-component](../../images/page-toolbar-custom-component.png) + +For this example, we've created a `MyToolbarItem` view component under the `/Pages/Identity/Users/MyToolbarItem` folder. + +`MyToolbarItemViewComponent.cs` content: + +````csharp +public class MyToolbarItemViewComponent : AbpViewComponent +{ + public IViewComponentResult Invoke() + { + return View("~/Pages/Identity/Users/MyToolbarItem/Default.cshtml"); + } +} +```` + +`Default.cshtml` content: + +````xml + + + +```` + +* `.cshtml` file can contain any type of component(s). It is a typical view component. +* `MyToolbarItemViewComponent` can inject and use any service if you need. + +Then you can add the `MyToolbarItemViewComponent` to the user management page: + +````csharp +Configure(options => +{ + options.Configure( + toolbar => + { + toolbar.AddComponent(); + } + ); +}); +```` + +* If your component accepts arguments (in the `Invoke`/`InvokeAsync` method), you can pass them to the `AddComponent` method as an anonymous object. + +#### Permissions + +If your button/component should be available based on a [permission/policy](../../Authorization.md), you can pass the permission/policy name as the `requiredPolicyName` parameter to the `AddButton` and `AddComponent` methods. + +### Add a Page Toolbar Contributor + +If you perform advanced custom logic while adding an item to a page toolbar, you can create a class that implements the `IPageToolbarContributor` interface or inherits from the `PageToolbarContributor` class: + +````csharp +public class MyToolbarContributor : PageToolbarContributor +{ + public override Task ContributeAsync(PageToolbarContributionContext context) + { + context.Items.Insert(0, new PageToolbarItem(typeof(MyToolbarItemViewComponent))); + + return Task.CompletedTask; + } +} +```` + +* You can use `context.ServiceProvider` to resolve dependencies if you need. + +Then add your class to the `Contributors` list: + +````csharp +Configure(options => +{ + options.Configure( + toolbar => + { + toolbar.Contributors.Add(new MyToolbarContributor()); + } + ); +}); +```` + diff --git a/docs/en/UI/Blazor/Page-Progress.md b/docs/en/UI/Blazor/Page-Progress.md new file mode 100644 index 0000000000..149c35293e --- /dev/null +++ b/docs/en/UI/Blazor/Page-Progress.md @@ -0,0 +1,3 @@ +# Blazor UI: Page Progress + +TODO \ No newline at end of file diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index edfebc9544..217467e666 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -353,22 +353,8 @@ "path": "PlugIn-Modules.md" }, { - "text": "Customizing the Application Modules", - "path": "Customizing-Application-Modules-Guide.md", - "items": [ - { - "text": "Extending Entities", - "path": "Customizing-Application-Modules-Extending-Entities.md" - }, - { - "text": "Overriding Services", - "path": "Customizing-Application-Modules-Overriding-Services.md" - }, - { - "text": "Overriding the User Interface", - "path": "Customizing-Application-Modules-Overriding-User-Interface.md" - } - ] + "text": "Customizing/Extending Modules", + "path": "Customizing-Application-Modules-Guide.md" }, { "text": "Best Practices", diff --git a/docs/en/images/page-toolbar-button.png b/docs/en/images/page-toolbar-button.png new file mode 100644 index 0000000000..05e3f9da11 Binary files /dev/null and b/docs/en/images/page-toolbar-button.png differ diff --git a/docs/en/images/page-toolbar-custom-component.png b/docs/en/images/page-toolbar-custom-component.png new file mode 100644 index 0000000000..a15ef4854c Binary files /dev/null and b/docs/en/images/page-toolbar-custom-component.png differ diff --git a/docs/zh-Hans/CLI.md b/docs/zh-Hans/CLI.md index 4c63dcd818..4a02b1c3c8 100644 --- a/docs/zh-Hans/CLI.md +++ b/docs/zh-Hans/CLI.md @@ -103,7 +103,7 @@ abp new Acme.BookStore * `--preview`: 使用最新的预览版本. * `--template-source` 或者 `-ts`: 指定自定义模板源用于生成项目,可以使用本地源和网络源(例如 `D:\local-templat` 或 `https://.../my-template-file.zip`). * `--create-solution-folder` 或者 `-csf`: 指定项目是在输出文件夹中的新文件夹中还是直接在输出文件夹中. -* `--connection-string` 或者 `-cs`: 重写所有 `appsettings.json` 文件的默认连接字符串. 默认连接字符串是 `Server=localhost;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true`. 默认的数据库提供程序是 `SQL Server`. 如果你使用EF Core但需要更改DBMS,可以按[这里所述](Entity-Framework-Core-Other-DBMS.md)进行更改(创建解决方案之后). +* `--connection-string` 或者 `-cs`: 重写所有 `appsettings.json` 文件的默认连接字符串. 默认连接字符串是 `Server=localhost;Database=MyProjectName;Trusted_Connection=True`. 默认的数据库提供程序是 `SQL Server`. 如果你使用EF Core但需要更改DBMS,可以按[这里所述](Entity-Framework-Core-Other-DBMS.md)进行更改(创建解决方案之后). * `--local-framework-ref --abp-path`: 使用对项目的本地引用,而不是替换为NuGet包引用. ### update diff --git a/docs/zh-Hans/Entity-Framework-Core-Migrations.md b/docs/zh-Hans/Entity-Framework-Core-Migrations.md index 266c0f46b0..8708516f76 100644 --- a/docs/zh-Hans/Entity-Framework-Core-Migrations.md +++ b/docs/zh-Hans/Entity-Framework-Core-Migrations.md @@ -588,7 +588,7 @@ public class IdentityRoleExtendingService : ITransientDependency ````json "ConnectionStrings": { - "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True" } ```` @@ -596,10 +596,10 @@ public class IdentityRoleExtendingService : ITransientDependency ````json "ConnectionStrings": { - "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True;MultipleActiveResultSets=true", - "AbpPermissionManagement": "Server=localhost;Database=BookStore_SecondDb;Trusted_Connection=True;MultipleActiveResultSets=true", - "AbpSettingManagement": "Server=localhost;Database=BookStore_SecondDb;Trusted_Connection=True;MultipleActiveResultSets=true", - "AbpAuditLogging": "Server=localhost;Database=BookStore_SecondDb;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True", + "AbpPermissionManagement": "Server=localhost;Database=BookStore_SecondDb;Trusted_Connection=True", + "AbpSettingManagement": "Server=localhost;Database=BookStore_SecondDb;Trusted_Connection=True", + "AbpAuditLogging": "Server=localhost;Database=BookStore_SecondDb;Trusted_Connection=True" } ```` diff --git a/docs/zh-Hans/Modules/Docs.md b/docs/zh-Hans/Modules/Docs.md index acc956be1b..1d09552e50 100644 --- a/docs/zh-Hans/Modules/Docs.md +++ b/docs/zh-Hans/Modules/Docs.md @@ -47,7 +47,7 @@ ABP框架的[文档](docs.abp.io)也是使用的此模块. ```json { "ConnectionStrings": { - "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProject;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProject;Trusted_Connection=True" } } ``` diff --git a/docs/zh-Hans/Samples/Microservice-Demo.md b/docs/zh-Hans/Samples/Microservice-Demo.md index 59fa98e057..ca8b90a03f 100644 --- a/docs/zh-Hans/Samples/Microservice-Demo.md +++ b/docs/zh-Hans/Samples/Microservice-Demo.md @@ -843,7 +843,7 @@ Swagger UI已配置,是此服务的默认页面. 如果你导航到URL`http://lo ````json "ConnectionStrings": { - "Default": "Server=localhost;Database=MsDemo_Identity;Trusted_Connection=True;MultipleActiveResultSets=true", + "Default": "Server=localhost;Database=MsDemo_Identity;Trusted_Connection=True", "Blogging": "mongodb://localhost/MsDemo_Blogging" } ```` @@ -969,8 +969,8 @@ public class ProductServiceMigrationDbContext : AbpDbContext - /// Gets first two, previous & current & next, last two pages + /// Gets first two, previous, current, next, last two pages /// private List GetPagesWithGaps() { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/ui-extensions.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/ui-extensions.js index eacfecc867..e6061219b0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/ui-extensions.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/ui-extensions.js @@ -96,7 +96,7 @@ get: _get }; })(); - + function initializeObjectExtensions() { var getShortEnumTypeName = function (enumType) { @@ -149,7 +149,7 @@ return defaultValue; } - + function localizeEnumMember(property, enumMemberValue) { var enumType = property.config.type; var enumInfo = abp.objectExtensions.enums[enumType]; @@ -188,10 +188,28 @@ var propertyName = propertyNames[i]; var propertyConfig = objectConfig.properties[propertyName]; if (propertyConfig.ui.onTable.isVisible) { - tableProperties.push({ - name: propertyName, - config: propertyConfig - }); + if (propertyName.endsWith("_Text")) { + var lookupPropertyName = propertyName.replace("_Text", ""); + var lookupProperty = objectConfig.properties[lookupPropertyName]; + if (lookupProperty) { + tableProperties.push({ + name: propertyName, + config: propertyConfig, + lookupPropertyName: lookupPropertyName, + lookupPropertyDisplayName: lookupProperty.displayName + }); + } else { + tableProperties.push({ + name: propertyName, + config: propertyConfig, + }); + } + } else { + tableProperties.push({ + name: propertyName, + config: propertyConfig, + }); + } } } @@ -199,19 +217,23 @@ } function getValueFromRow(property, row) { - return row.extraProperties[property.name];; + return row.extraProperties[property.name]; } function convertPropertyToColumnConfig(property) { var columnConfig = { - title: localizeDisplayName(property.name, property.config.displayName), data: "extraProperties." + property.name, orderable: false }; + if (property.lookupPropertyName) { + columnConfig.title = localizeDisplayName(property.lookupPropertyName, property.lookupPropertyDisplayName); + } else { + columnConfig.title = localizeDisplayName(property.name, property.config.displayName); + } if (property.config.typeSimple === 'enum') { - columnConfig.render = function(data, type, row) { + columnConfig.render = function (data, type, row) { var value = getValueFromRow(property, row); return localizeEnumMember(property, value); } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs index 552ce7e04e..43dedf916f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs @@ -46,7 +46,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow var options = CreateOptions(context, unitOfWorkAttr); //Trying to begin a reserved UOW by AbpUnitOfWorkMiddleware - if (_unitOfWorkManager.TryBeginReserved(AbpUnitOfWorkMiddleware.UnitOfWorkReservationName, options)) + if (_unitOfWorkManager.TryBeginReserved(UnitOfWork.UnitOfWorkReservationName, options)) { var result = await next(); if (!Succeed(result)) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs index bcef10ecd4..960c47b591 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs @@ -50,7 +50,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow var options = CreateOptions(context, unitOfWorkAttr); //Trying to begin a reserved UOW by AbpUnitOfWorkMiddleware - if (_unitOfWorkManager.TryBeginReserved(AbpUnitOfWorkMiddleware.UnitOfWorkReservationName, options)) + if (_unitOfWorkManager.TryBeginReserved(UnitOfWork.UnitOfWorkReservationName, options)) { var result = await next(); if (!Succeed(result)) diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs index c9ac1be509..aeb6f8a8c0 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs @@ -7,8 +7,6 @@ namespace Volo.Abp.AspNetCore.Uow { public class AbpUnitOfWorkMiddleware : IMiddleware, ITransientDependency { - public const string UnitOfWorkReservationName = "_AbpActionUnitOfWork"; - private readonly IUnitOfWorkManager _unitOfWorkManager; public AbpUnitOfWorkMiddleware(IUnitOfWorkManager unitOfWorkManager) @@ -18,7 +16,7 @@ namespace Volo.Abp.AspNetCore.Uow public async Task InvokeAsync(HttpContext context, RequestDelegate next) { - using (var uow = _unitOfWorkManager.Reserve(UnitOfWorkReservationName)) + using (var uow = _unitOfWorkManager.Reserve(UnitOfWork.UnitOfWorkReservationName)) { await next(context); await uow.CompleteAsync(context.RequestAborted); diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProvider.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProvider.cs new file mode 100644 index 0000000000..fd1d20d905 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProvider.cs @@ -0,0 +1,52 @@ +using System; +using System.Net.Http; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Uow; + +namespace Volo.Abp.AspNetCore.Uow +{ + public class AspNetCoreUnitOfWorkTransactionBehaviourProvider : IUnitOfWorkTransactionBehaviourProvider, ISingletonDependency + { + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly AspNetCoreUnitOfWorkTransactionBehaviourProviderOptions _options; + + public virtual bool? IsTransactional + { + get + { + var httpContext = _httpContextAccessor.HttpContext; + if (httpContext == null) + { + return null; + } + + var currentUrl = httpContext.Request.Path.Value; + if (currentUrl != null) + { + foreach (var url in _options.NonTransactionalUrls) + { + if (currentUrl.StartsWith(url, StringComparison.OrdinalIgnoreCase)) + { + return false; + } + } + } + + return !string.Equals( + httpContext.Request.Method, + HttpMethod.Get.Method, StringComparison.OrdinalIgnoreCase + ); + } + } + + public AspNetCoreUnitOfWorkTransactionBehaviourProvider( + IHttpContextAccessor httpContextAccessor, + IOptions options) + { + _httpContextAccessor = httpContextAccessor; + _options = options.Value; + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProviderOptions.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProviderOptions.cs new file mode 100644 index 0000000000..dd612a008d --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProviderOptions.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace Volo.Abp.AspNetCore.Uow +{ + public class AspNetCoreUnitOfWorkTransactionBehaviourProviderOptions + { + public List NonTransactionalUrls { get; } + + public AspNetCoreUnitOfWorkTransactionBehaviourProviderOptions() + { + NonTransactionalUrls = new List + { + "/connect/" + }; + } + } +} diff --git a/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AuthorizationOptionsExtensions.cs b/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AuthorizationOptionsExtensions.cs index 499c2431c5..516e842563 100644 --- a/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AuthorizationOptionsExtensions.cs +++ b/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AuthorizationOptionsExtensions.cs @@ -11,9 +11,9 @@ namespace Microsoft.AspNetCore.Authorization /// /// Gets all policies. - /// + /// /// IMPORTANT NOTE: Use this method carefully. - /// It relies on reflection to get all policies from a private field of the . + /// It relies on reflection to get all policies from a private field of the . /// This method may be removed in the future if internals of changes. /// /// @@ -23,4 +23,4 @@ namespace Microsoft.AspNetCore.Authorization return ((IDictionary) PolicyMapProperty.GetValue(options)).Keys.ToList(); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs index 602fdd9c50..38873fe1b8 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs @@ -54,7 +54,7 @@ namespace Volo.Abp.Authorization.Permissions /// /// Disabling a permission would be helpful to hide a related application /// functionality from users/clients. - /// + /// /// Default: true. /// public bool IsEnabled { get; set; } @@ -64,8 +64,8 @@ namespace Volo.Abp.Authorization.Permissions /// /// Name of the property /// - /// Returns the value in the dictionary by given . - /// Returns null if given is not present in the dictionary. + /// Returns the value in the dictionary by given . + /// Returns null if given is not present in the dictionary. /// public object this[string name] { @@ -74,7 +74,7 @@ namespace Volo.Abp.Authorization.Permissions } protected internal PermissionDefinition( - [NotNull] string name, + [NotNull] string name, ILocalizableString displayName = null, MultiTenancySides multiTenancySide = MultiTenancySides.Both, bool isEnabled = true) @@ -90,14 +90,14 @@ namespace Volo.Abp.Authorization.Permissions } public virtual PermissionDefinition AddChild( - [NotNull] string name, + [NotNull] string name, ILocalizableString displayName = null, MultiTenancySides multiTenancySide = MultiTenancySides.Both, bool isEnabled = true) { var child = new PermissionDefinition( - name, - displayName, + name, + displayName, multiTenancySide, isEnabled) { @@ -138,4 +138,4 @@ namespace Volo.Abp.Authorization.Permissions return $"[{nameof(PermissionDefinition)} {Name}]"; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionGroupDefinition.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionGroupDefinition.cs index 5038e8e064..6d3a937a94 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionGroupDefinition.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionGroupDefinition.cs @@ -36,8 +36,8 @@ namespace Volo.Abp.Authorization.Permissions /// /// Name of the property /// - /// Returns the value in the dictionary by given . - /// Returns null if given is not present in the dictionary. + /// Returns the value in the dictionary by given . + /// Returns null if given is not present in the dictionary. /// public object this[string name] { @@ -46,7 +46,7 @@ namespace Volo.Abp.Authorization.Permissions } protected internal PermissionGroupDefinition( - string name, + string name, ILocalizableString displayName = null, MultiTenancySides multiTenancySide = MultiTenancySides.Both) { @@ -59,7 +59,7 @@ namespace Volo.Abp.Authorization.Permissions } public virtual PermissionDefinition AddPermission( - string name, + string name, ILocalizableString displayName = null, MultiTenancySides multiTenancySide = MultiTenancySides.Both, bool isEnabled = true) @@ -131,4 +131,4 @@ namespace Volo.Abp.Authorization.Permissions return null; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConventionalRegistrar.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConventionalRegistrar.cs new file mode 100644 index 0000000000..86fc494676 --- /dev/null +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConventionalRegistrar.cs @@ -0,0 +1,34 @@ +using System; +using System.Linq; +using AutoMapper; +using AutoMapper.Internal; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AutoMapper +{ + public class AbpAutoMapperConventionalRegistrar : ConventionalRegistrarBase + { + protected readonly Type[] OpenTypes = { + typeof(IValueResolver<,,>), + typeof(IMemberValueResolver<,,,>), + typeof(ITypeConverter<,>), + typeof(IValueConverter<,>), + typeof(IMappingAction<,>) + }; + + public override void AddType(IServiceCollection services, Type type) + { + if (IsConventionalRegistrationDisabled(type)) + { + return; + } + + if (type.IsClass && !type.IsAbstract && OpenTypes.Any(type.ImplementsGenericInterface)) + { + services.TryAddTransient(type); + } + } + } +} diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs index 214872e371..25707e3899 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs @@ -13,24 +13,23 @@ namespace Volo.Abp.AutoMapper typeof(AbpObjectMappingModule), typeof(AbpObjectExtendingModule), typeof(AbpAuditingModule) - )] + )] public class AbpAutoMapperModule : AbpModule { - public override void ConfigureServices(ServiceConfigurationContext context) + public override void PreConfigureServices(ServiceConfigurationContext context) { - context.Services.AddAutoMapperObjectMapper(); - - var mapperAccessor = new MapperAccessor(); - context.Services.AddSingleton(_ => mapperAccessor); - context.Services.AddSingleton(_ => mapperAccessor); + context.Services.AddConventionalRegistrar(new AbpAutoMapperConventionalRegistrar()); } - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + public override void ConfigureServices(ServiceConfigurationContext context) { - CreateMappings(context.ServiceProvider); + context.Services.AddAutoMapperObjectMapper(); + + context.Services.AddSingleton(provider => CreateMappings(provider)); + context.Services.AddSingleton(provider => provider.GetRequiredService()); } - private void CreateMappings(IServiceProvider serviceProvider) + private MapperAccessor CreateMappings(IServiceProvider serviceProvider) { using (var scope = serviceProvider.CreateScope()) { @@ -48,7 +47,7 @@ namespace Volo.Abp.AutoMapper { foreach (var profileType in options.ValidatingProfiles) { - config.AssertConfigurationIsValid(((Profile)Activator.CreateInstance(profileType)).ProfileName); + config.AssertConfigurationIsValid(((Profile) Activator.CreateInstance(profileType)).ProfileName); } } @@ -59,7 +58,10 @@ namespace Volo.Abp.AutoMapper ValidateAll(mapperConfiguration); - scope.ServiceProvider.GetRequiredService().Mapper = mapperConfiguration.CreateMapper(); + return new MapperAccessor + { + Mapper = new Mapper(mapperConfiguration, serviceProvider.GetService) + }; } } } diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacRegistration.cs b/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacRegistration.cs index e0f7ec50ad..f1a6264683 100644 --- a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacRegistration.cs +++ b/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacRegistration.cs @@ -1,6 +1,6 @@ // This software is part of the Autofac IoC container // Copyright © 2015 Autofac Contributors -// http://autofac.org +// https://autofac.org // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -24,10 +24,13 @@ // OTHER DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using Autofac.Builder; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Autofac; +using Volo.Abp; using Volo.Abp.Modularity; namespace Autofac.Extensions.DependencyInjection @@ -46,16 +49,62 @@ namespace Autofac.Extensions.DependencyInjection /// The into which the registrations should be made. /// /// - /// The set of service descriptors to register in the container. + /// A container builder that can be used to create an . /// public static void Populate( - this ContainerBuilder builder, - IServiceCollection services) + this ContainerBuilder builder, + IServiceCollection services) { - builder.RegisterType().As(); - builder.RegisterType().As(); + Populate(builder, services, null); + } + + /// + /// Populates the Autofac container builder with the set of registered service descriptors + /// and makes and + /// available in the container. Using this overload is incompatible with the ASP.NET Core + /// support for . + /// + /// + /// The into which the registrations should be made. + /// + /// + /// A container builder that can be used to create an . + /// + /// + /// If provided and not then all registrations with lifetime are registered + /// using + /// with provided + /// instead of using . + /// + /// + /// + /// Specifying a addresses a specific case where you have + /// an application that uses Autofac but where you need to isolate a set of services in a child scope. For example, + /// if you have a large application that self-hosts ASP.NET Core items, you may want to isolate the ASP.NET + /// Core registrations in a child lifetime scope so they don't show up for the rest of the application. + /// This overload allows that. Note it is the developer's responsibility to execute this and create an + /// using the child lifetime scope. + /// + /// + public static void Populate( + this ContainerBuilder builder, + IServiceCollection services, + object lifetimeScopeTagForSingletons) + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } - Register(builder, services); + builder.RegisterType().As().ExternallyOwned(); + var autofacServiceScopeFactory = typeof(AutofacServiceProvider).Assembly.GetType("Autofac.Extensions.DependencyInjection.AutofacServiceScopeFactory"); + if (autofacServiceScopeFactory == null) + { + throw new AbpException("Unable get type of Autofac.Extensions.DependencyInjection.AutofacServiceScopeFactory!"); + } + builder.RegisterType(autofacServiceScopeFactory).As(); + + Register(builder, services, lifetimeScopeTagForSingletons); } /// @@ -65,18 +114,33 @@ namespace Autofac.Extensions.DependencyInjection /// The object registration style. /// The registration being built. /// The lifecycle specified on the service registration. + /// + /// If not then all registrations with lifetime are registered + /// using + /// with provided + /// instead of using . + /// /// /// The , configured with the proper lifetime scope, /// and available for additional configuration. /// private static IRegistrationBuilder ConfigureLifecycle( - this IRegistrationBuilder registrationBuilder, - ServiceLifetime lifecycleKind) + this IRegistrationBuilder registrationBuilder, + ServiceLifetime lifecycleKind, + object lifetimeScopeTagForSingleton) { switch (lifecycleKind) { case ServiceLifetime.Singleton: - registrationBuilder.SingleInstance(); + if (lifetimeScopeTagForSingleton == null) + { + registrationBuilder.SingleInstance(); + } + else + { + registrationBuilder.InstancePerMatchingLifetimeScope(lifetimeScopeTagForSingleton); + } + break; case ServiceLifetime.Scoped: registrationBuilder.InstancePerLifetimeScope(); @@ -96,59 +160,67 @@ namespace Autofac.Extensions.DependencyInjection /// The into which the registrations should be made. /// /// - /// The set of service descriptors to register in the container. + /// A container builder that can be used to create an . + /// + /// + /// If not then all registrations with lifetime are registered + /// using + /// with provided + /// instead of using . /// + [SuppressMessage("CA2000", "CA2000", Justification = "Registrations created here are disposed when the built container is disposed.")] private static void Register( - ContainerBuilder builder, - IServiceCollection services) + ContainerBuilder builder, + IServiceCollection services, + object lifetimeScopeTagForSingletons) { var moduleContainer = services.GetSingletonInstance(); var registrationActionList = services.GetRegistrationActionList(); - foreach (var service in services) + foreach (var descriptor in services) { - if (service.ImplementationType != null) + if (descriptor.ImplementationType != null) { // Test if the an open generic type is being registered - var serviceTypeInfo = service.ServiceType.GetTypeInfo(); + var serviceTypeInfo = descriptor.ServiceType.GetTypeInfo(); if (serviceTypeInfo.IsGenericTypeDefinition) { builder - .RegisterGeneric(service.ImplementationType) - .As(service.ServiceType) - .ConfigureLifecycle(service.Lifetime) + .RegisterGeneric(descriptor.ImplementationType) + .As(descriptor.ServiceType) + .ConfigureLifecycle(descriptor.Lifetime, lifetimeScopeTagForSingletons) .FindConstructorsWith(new AbpAutofacConstructorFinder()) .ConfigureAbpConventions(moduleContainer, registrationActionList); } else { builder - .RegisterType(service.ImplementationType) - .As(service.ServiceType) - .ConfigureLifecycle(service.Lifetime) + .RegisterType(descriptor.ImplementationType) + .As(descriptor.ServiceType) + .ConfigureLifecycle(descriptor.Lifetime, lifetimeScopeTagForSingletons) .FindConstructorsWith(new AbpAutofacConstructorFinder()) .ConfigureAbpConventions(moduleContainer, registrationActionList); } } - else if (service.ImplementationFactory != null) + else if (descriptor.ImplementationFactory != null) { - var registration = RegistrationBuilder.ForDelegate(service.ServiceType, (context, parameters) => - { - var serviceProvider = context.Resolve(); - return service.ImplementationFactory(serviceProvider); - }) - .ConfigureLifecycle(service.Lifetime) - .CreateRegistration(); - //TODO: ConfigureAbpConventions ? + var registration = RegistrationBuilder.ForDelegate(descriptor.ServiceType, (context, parameters) => + { + var serviceProvider = context.Resolve(); + return descriptor.ImplementationFactory(serviceProvider); + }) + .ConfigureLifecycle(descriptor.Lifetime, lifetimeScopeTagForSingletons) + .CreateRegistration(); + //TODO: ConfigureAbpConventions ? builder.RegisterComponent(registration); } else { builder - .RegisterInstance(service.ImplementationInstance) - .As(service.ServiceType) - .ConfigureLifecycle(service.Lifetime); + .RegisterInstance(descriptor.ImplementationInstance) + .As(descriptor.ServiceType) + .ConfigureLifecycle(descriptor.Lifetime, null); } } } diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacServiceProvider.cs b/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacServiceProvider.cs deleted file mode 100644 index 1c1a24ff66..0000000000 --- a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacServiceProvider.cs +++ /dev/null @@ -1,122 +0,0 @@ -// This software is part of the Autofac IoC container -// Copyright © 2015 Autofac Contributors -// https://autofac.org -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -using System; -using Microsoft.Extensions.DependencyInjection; - -namespace Autofac.Extensions.DependencyInjection -{ - /// - /// Autofac implementation of the ASP.NET Core . - /// - /// - /// - public class AutofacServiceProvider : IServiceProvider, ISupportRequiredService, IDisposable - { - private readonly ILifetimeScope _lifetimeScope; - - private bool _disposed = false; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The lifetime scope from which services will be resolved. - /// - public AutofacServiceProvider(ILifetimeScope lifetimeScope) - { - this._lifetimeScope = lifetimeScope; - } - - /// - /// Gets service of type from the - /// and requires it be present. - /// - /// - /// An object that specifies the type of service object to get. - /// - /// - /// A service object of type . - /// - /// - /// Thrown if the isn't registered with the container. - /// - /// - /// Thrown if the object can't be resolved from the container. - /// - public object GetRequiredService(Type serviceType) - { - return this._lifetimeScope.Resolve(serviceType); - } - - /// - /// Gets the service object of the specified type. - /// - /// - /// An object that specifies the type of service object to get. - /// - /// - /// A service object of type ; or - /// if there is no service object of type . - /// - public object GetService(Type serviceType) - { - return this._lifetimeScope.ResolveOptional(serviceType); - } - - /// - /// Gets the underlying instance of . - /// - public ILifetimeScope LifetimeScope => _lifetimeScope; - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// - /// to release both managed and unmanaged resources; - /// to release only unmanaged resources. - /// - protected virtual void Dispose(bool disposing) - { - if (!this._disposed) - { - this._disposed = true; - if (disposing) - { - this._lifetimeScope.Dispose(); - } - } - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - this.Dispose(true); - GC.SuppressFinalize(this); - } - } -} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacServiceProviderFactory.cs b/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacServiceProviderFactory.cs deleted file mode 100644 index 21a7ca331d..0000000000 --- a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacServiceProviderFactory.cs +++ /dev/null @@ -1,77 +0,0 @@ -// This software is part of the Autofac IoC container -// Copyright © 2017 Autofac Contributors -// http://autofac.org -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -using System; -using Microsoft.Extensions.DependencyInjection; - -namespace Autofac.Extensions.DependencyInjection -{ - /// - /// A factory for creating a and an . - /// - public class AutofacServiceProviderFactory : IServiceProviderFactory - { - private readonly Action _configurationAction; - - /// - /// Initializes a new instance of the class. - /// - /// Action on a that adds component registrations to the container. - public AutofacServiceProviderFactory(Action configurationAction = null) - { - _configurationAction = configurationAction ?? (builder => { }); - } - - /// - /// Creates a container builder from an . - /// - /// The collection of services - /// A container builder that can be used to create an . - public ContainerBuilder CreateBuilder(IServiceCollection services) - { - var builder = new ContainerBuilder(); - - builder.Populate(services); - - _configurationAction(builder); - - return builder; - } - - /// - /// Creates an from the container builder. - /// - /// The container builder - /// An - public IServiceProvider CreateServiceProvider(ContainerBuilder containerBuilder) - { - if (containerBuilder == null) throw new ArgumentNullException(nameof(containerBuilder)); - - var container = containerBuilder.Build(); - - return new AutofacServiceProvider(container); - } - } -} diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacServiceScope.cs b/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacServiceScope.cs deleted file mode 100644 index 425c6769da..0000000000 --- a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacServiceScope.cs +++ /dev/null @@ -1,67 +0,0 @@ -// This software is part of the Autofac IoC container -// Copyright © 2015 Autofac Contributors -// http://autofac.org -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -using System; -using Microsoft.Extensions.DependencyInjection; - -namespace Autofac.Extensions.DependencyInjection -{ - /// - /// Autofac implementation of the ASP.NET Core . - /// - /// - internal class AutofacServiceScope : IServiceScope - { - private readonly ILifetimeScope _lifetimeScope; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The lifetime scope from which services should be resolved for this service scope. - /// - public AutofacServiceScope(ILifetimeScope lifetimeScope) - { - this._lifetimeScope = lifetimeScope; - this.ServiceProvider = this._lifetimeScope.Resolve(); - } - - /// - /// Gets an corresponding to this service scope. - /// - /// - /// An that can be used to resolve dependencies from the scope. - /// - public IServiceProvider ServiceProvider { get; } - - /// - /// Disposes of the lifetime scope and resolved disposable services. - /// - public void Dispose() - { - this._lifetimeScope.Dispose(); - } - } -} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacServiceScopeFactory.cs b/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacServiceScopeFactory.cs deleted file mode 100644 index 31917fd079..0000000000 --- a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacServiceScopeFactory.cs +++ /dev/null @@ -1,65 +0,0 @@ -// This software is part of the Autofac IoC container -// Copyright © 2015 Autofac Contributors -// http://autofac.org -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -using System.Diagnostics.CodeAnalysis; -using Microsoft.Extensions.DependencyInjection; - -namespace Autofac.Extensions.DependencyInjection -{ - /// - /// Autofac implementation of the ASP.NET Core . - /// - /// - [SuppressMessage("Microsoft.ApiDesignGuidelines", "CA2213", Justification = "The creator of the root service lifetime scope is responsible for disposal.")] - internal class AutofacServiceScopeFactory : IServiceScopeFactory - { - private readonly ILifetimeScope _lifetimeScope; - - /// - /// Initializes a new instance of the class. - /// - /// The lifetime scope. - public AutofacServiceScopeFactory(ILifetimeScope lifetimeScope) - { - this._lifetimeScope = lifetimeScope; - } - - /// - /// Creates an which contains an - /// used to resolve dependencies within - /// the scope. - /// - /// - /// An controlling the lifetime of the scope. Once - /// this is disposed, any scoped services that have been resolved - /// from the - /// will also be disposed. - /// - public IServiceScope CreateScope() - { - return new AutofacServiceScope(this._lifetimeScope.BeginLifetimeScope()); - } - } -} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj b/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj index ec9e4c0364..a57ac74e62 100644 --- a/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj +++ b/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj @@ -15,8 +15,10 @@ - + + + diff --git a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/IAsyncBackgroundJob.cs b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/IAsyncBackgroundJob.cs index 262d95d35b..18f38128db 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/IAsyncBackgroundJob.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/IAsyncBackgroundJob.cs @@ -8,9 +8,9 @@ namespace Volo.Abp.BackgroundJobs public interface IAsyncBackgroundJob { /// - /// Executes the job with the . + /// Executes the job with the . /// /// Job arguments. Task ExecuteAsync(TArgs args); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/IBackgroundJob.cs b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/IBackgroundJob.cs index e7c942ec4c..94b75f4c91 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/IBackgroundJob.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/IBackgroundJob.cs @@ -6,9 +6,9 @@ public interface IBackgroundJob { /// - /// Executes the job with the . + /// Executes the job with the . /// /// Job arguments. void Execute(TArgs args); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpBackgroundWorkersQuartzModule.cs b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpBackgroundWorkersQuartzModule.cs index 9cfc748c4e..a47f8dac77 100644 --- a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpBackgroundWorkersQuartzModule.cs +++ b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpBackgroundWorkersQuartzModule.cs @@ -26,20 +26,20 @@ namespace Volo.Abp.BackgroundWorkers.Quartz public override void OnPreApplicationInitialization(ApplicationInitializationContext context) { - var options = context.ServiceProvider.GetService>().Value; + var options = context.ServiceProvider.GetRequiredService>().Value; if (!options.IsEnabled) { - var quartzOptions = context.ServiceProvider.GetService>().Value; - quartzOptions.StartSchedulerFactory = scheduler => Task.CompletedTask; + var quartzOptions = context.ServiceProvider.GetRequiredService>().Value; + quartzOptions.StartSchedulerFactory = _ => Task.CompletedTask; } } public override void OnApplicationInitialization(ApplicationInitializationContext context) { - var quartzBackgroundWorkerOptions = context.ServiceProvider.GetService>().Value; + var quartzBackgroundWorkerOptions = context.ServiceProvider.GetRequiredService>().Value; if (quartzBackgroundWorkerOptions.IsAutoRegisterEnabled) { - var backgroundWorkerManager = context.ServiceProvider.GetService(); + var backgroundWorkerManager = context.ServiceProvider.GetRequiredService(); var works = context.ServiceProvider.GetServices().Where(x=>x.AutoRegister); foreach (var work in works) diff --git a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerAdapter.cs b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerAdapter.cs index 970beea3f0..0b75f389fe 100644 --- a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerAdapter.cs +++ b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerAdapter.cs @@ -57,7 +57,7 @@ namespace Volo.Abp.BackgroundWorkers.Quartz .Build(); } - public async override Task Execute(IJobExecutionContext context) + public override async Task Execute(IJobExecutionContext context) { var worker = (IBackgroundWorker) ServiceProvider.GetService(typeof(TWorker)); var workerContext = new PeriodicBackgroundWorkerContext(ServiceProvider); diff --git a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerManager.cs b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerManager.cs index d670c1db98..582a7dd520 100644 --- a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerManager.cs +++ b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerManager.cs @@ -19,14 +19,17 @@ namespace Volo.Abp.BackgroundWorkers.Quartz public virtual async Task StartAsync(CancellationToken cancellationToken = default) { - await _scheduler.ResumeAll(cancellationToken); + if (_scheduler.IsStarted && _scheduler.InStandbyMode) + { + await _scheduler.Start(cancellationToken); + } } public virtual async Task StopAsync(CancellationToken cancellationToken = default) { - if (!_scheduler.IsShutdown) + if (_scheduler.IsStarted && !_scheduler.InStandbyMode) { - await _scheduler.PauseAll(cancellationToken); + await _scheduler.Standby(cancellationToken); } } diff --git a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs index 612034af19..9a820600bd 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs @@ -439,10 +439,10 @@ namespace Volo.Abp.BlazoriseUI } /// - /// Calls IAuthorizationService.CheckAsync for the given . + /// Calls IAuthorizationService.CheckAsync for the given . /// Throws if given policy was not granted for the current user. /// - /// Does nothing if is null or empty. + /// Does nothing if is null or empty. /// /// A policy name to check protected virtual async Task CheckPolicyAsync([CanBeNull] string policyName) diff --git a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerFactoryExtensions.cs b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerFactoryExtensions.cs index 1dc51a2a72..e2d5ff25e9 100644 --- a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerFactoryExtensions.cs +++ b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerFactoryExtensions.cs @@ -6,7 +6,6 @@ /// Gets a named container. /// /// The blob container manager - /// Cancellation token /// /// The container object. /// @@ -19,4 +18,4 @@ ); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index 3bd8aecbc1..c4942d04ab 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -150,6 +150,13 @@ namespace Volo.Abp.Cli.Commands Logger.LogInformation("Output folder: " + outputFolder); + if (connectionString == null && + databaseManagementSystem != DatabaseManagementSystem.NotSpecified && + databaseManagementSystem != DatabaseManagementSystem.SQLServer) + { + connectionString = GetNewConnectionStringByDbms(databaseManagementSystem, outputFolder); + } + commandLineArgs.Options.Add(CliConsts.Command, commandLineArgs.Command); var result = await TemplateProjectBuilder.BuildAsync( @@ -219,6 +226,24 @@ namespace Volo.Abp.Cli.Commands } } + private string GetNewConnectionStringByDbms(DatabaseManagementSystem databaseManagementSystem, string outputFolder) + { + switch (databaseManagementSystem) + { + case DatabaseManagementSystem.MySQL: + return "Server=localhost;Port=3306;Database=MyProjectName;Uid=root;Pwd=myPassword;"; + case DatabaseManagementSystem.PostgreSQL: + return "User ID=root;Password=myPassword;Host=localhost;Port=5432;Database=MyProjectName;Pooling=true;Min Pool Size=0;Max Pool Size=100;Connection Lifetime=0;"; + //case DatabaseManagementSystem.Oracle: + case DatabaseManagementSystem.OracleDevart: + return "Data Source=MyProjectName;Integrated Security=yes;"; + case DatabaseManagementSystem.SQLite: + return $"Data Source={Path.Combine(outputFolder,"database\\MyProjectName.db")};Version=3;"; + default: + return null; + } + } + private void DeleteMigrationsIfNeeded(DatabaseProvider databaseProvider, DatabaseManagementSystem databaseManagementSystem, string outputFolder) { if (databaseManagementSystem == DatabaseManagementSystem.NotSpecified || databaseManagementSystem == DatabaseManagementSystem.SQLServer) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs index 9590001ea4..513c2b4198 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs @@ -17,6 +17,12 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building pipeline.Steps.Add(new ProjectReferenceReplaceStep()); pipeline.Steps.Add(new TemplateCodeDeleteStep()); + + if (context.BuildArgs.ConnectionString != null) + { + pipeline.Steps.Add(new ConnectionStringChangeStep()); + } + pipeline.Steps.Add(new SolutionRenameStep()); if (context.Template.Name == AppProTemplate.TemplateName || @@ -37,11 +43,6 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building pipeline.Steps.Add(new RemoveRootFolderStep()); } - if (context.BuildArgs.ConnectionString != null) - { - pipeline.Steps.Add(new ConnectionStringChangeStep()); - } - pipeline.Steps.Add(new CreateProjectResultZipStep()); return pipeline; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs index 07896b49a1..8cfbe5cb94 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs @@ -205,14 +205,25 @@ namespace Volo.Abp.Cli.ProjectModification string postFix) { var srcPath = Path.Combine(Path.GetDirectoryName(moduleSolutionFile), targetFolder); + + if (!Directory.Exists(srcPath)) + { + return; + } + var projectFolderPath = Directory.GetDirectories(srcPath).FirstOrDefault(d=> d.EndsWith(postFix)); + + if (projectFolderPath == null) + { + return; + } + await SolutionFileModifier.RemoveProjectFromSolutionFileAsync(moduleSolutionFile, new DirectoryInfo(projectFolderPath).Name); if (Directory.Exists(projectFolderPath)) { Directory.Delete(projectFolderPath, true); } - } private async Task ChangeDomainTestReferenceToMongoDB(ModuleWithMastersInfo module, string moduleSolutionFile) diff --git a/framework/src/Volo.Abp.Cli/Properties/launchSettings.json b/framework/src/Volo.Abp.Cli/Properties/launchSettings.json deleted file mode 100644 index 6846f7adbd..0000000000 --- a/framework/src/Volo.Abp.Cli/Properties/launchSettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "profiles": { - "Volo.Abp.Cli": { - "commandName": "Project", - "commandLineArgs": "bundle --skip-version-check", - "workingDirectory": "C:\\Github\\volo\\abp\\templates\\app-pro\\aspnet-core\\src\\MyCompanyName.MyProjectName.Blazor" - } - } -} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/System/AbpStringExtensions.cs b/framework/src/Volo.Abp.Core/System/AbpStringExtensions.cs index 76ae06a5e0..f272484611 100644 --- a/framework/src/Volo.Abp.Core/System/AbpStringExtensions.cs +++ b/framework/src/Volo.Abp.Core/System/AbpStringExtensions.cs @@ -88,7 +88,7 @@ namespace System /// Gets index of nth occurrence of a char in a string. /// /// source string to be searched - /// Char to search in + /// Char to search in /// Count of the occurrence public static int NthIndexOf(this string str, char c, int n) { diff --git a/framework/src/Volo.Abp.Core/System/Collections/Generic/AbpCollectionExtensions.cs b/framework/src/Volo.Abp.Core/System/Collections/Generic/AbpCollectionExtensions.cs index e014ee9e21..f55bdd3bc8 100644 --- a/framework/src/Volo.Abp.Core/System/Collections/Generic/AbpCollectionExtensions.cs +++ b/framework/src/Volo.Abp.Core/System/Collections/Generic/AbpCollectionExtensions.cs @@ -107,7 +107,7 @@ namespace System.Collections.Generic } /// - /// Removes all items from the collection those satisfy the given . + /// Removes all items from the collection. /// /// Type of the items in the collection /// The collection diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Reflection/TypeFinder.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Reflection/TypeFinder.cs index 6576f08318..71ea895fd2 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Reflection/TypeFinder.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Reflection/TypeFinder.cs @@ -37,7 +37,7 @@ namespace Volo.Abp.Reflection allTypes.AddRange(typesInThisAssembly.Where(type => type != null)); } - catch (Exception ex) + catch { //TODO: Trigger a global event? } @@ -46,4 +46,4 @@ namespace Volo.Abp.Reflection return allTypes; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Text/Formatting/FormattedStringValueExtracter.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Text/Formatting/FormattedStringValueExtracter.cs index 6d21fc2a73..00d25681e4 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Text/Formatting/FormattedStringValueExtracter.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Text/Formatting/FormattedStringValueExtracter.cs @@ -11,7 +11,7 @@ namespace Volo.Abp.Text.Formatting /// /// /// Say that str is "My name is Neo." and format is "My name is {name}.". - /// Then Extract method gets "Neo" as "name". + /// Then Extract method gets "Neo" as "name". /// public class FormattedStringValueExtracter { @@ -84,7 +84,7 @@ namespace Volo.Abp.Text.Formatting } /// - /// Checks if given fits to given . + /// Checks if given fits to given . /// Also gets extracted values. /// /// String including dynamic values @@ -127,4 +127,4 @@ namespace Volo.Abp.Text.Formatting } } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/DapperRepository.cs b/framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/DapperRepository.cs index cdb03f8515..39b3eed249 100644 --- a/framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/DapperRepository.cs +++ b/framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/DapperRepository.cs @@ -1,4 +1,6 @@ -using System.Data; +using System; +using System.Data; +using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage; using Volo.Abp.EntityFrameworkCore; @@ -16,8 +18,14 @@ namespace Volo.Abp.Domain.Repositories.Dapper _dbContextProvider = dbContextProvider; } + [Obsolete("Use GetDbConnectionAsync method.")] public IDbConnection DbConnection => _dbContextProvider.GetDbContext().Database.GetDbConnection(); + public async Task GetDbConnectionAsync() => (await _dbContextProvider.GetDbContextAsync()).Database.GetDbConnection(); + + [Obsolete("Use GetDbTransactionAsync method.")] public IDbTransaction DbTransaction => _dbContextProvider.GetDbContext().Database.CurrentTransaction?.GetDbTransaction(); + + public async Task GetDbTransactionAsync() => (await _dbContextProvider.GetDbContextAsync()).Database.CurrentTransaction?.GetDbTransaction(); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/IDapperRepository.cs b/framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/IDapperRepository.cs index f45be08b54..8145c646a0 100644 --- a/framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/IDapperRepository.cs +++ b/framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/IDapperRepository.cs @@ -1,11 +1,19 @@ -using System.Data; +using System; +using System.Data; +using System.Threading.Tasks; namespace Volo.Abp.Domain.Repositories.Dapper { public interface IDapperRepository { + [Obsolete("Use GetDbConnectionAsync method.")] IDbConnection DbConnection { get; } + Task GetDbConnectionAsync(); + + [Obsolete("Use GetDbTransactionAsync method.")] IDbTransaction DbTransaction { get; } + + Task GetDbTransactionAsync(); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedContext.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedContext.cs index 6cda2f6e39..6c470312d8 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedContext.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedContext.cs @@ -13,8 +13,8 @@ namespace Volo.Abp.Data /// /// Name of the property /// - /// Returns the value in the dictionary by given . - /// Returns null if given is not present in the dictionary. + /// Returns the value in the dictionary by given . + /// Returns null if given is not present in the dictionary. /// [CanBeNull] public object this[string name] @@ -45,4 +45,4 @@ namespace Volo.Abp.Data return this; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/DefaultConnectionStringResolver.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/DefaultConnectionStringResolver.cs index 84221fb271..4d5ce2fb27 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/DefaultConnectionStringResolver.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/DefaultConnectionStringResolver.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; @@ -14,7 +15,18 @@ namespace Volo.Abp.Data Options = options.Value; } + [Obsolete("Use ResolveAsync method.")] public virtual string Resolve(string connectionStringName = null) + { + return ResolveInternal(connectionStringName); + } + + public virtual Task ResolveAsync(string connectionStringName = null) + { + return Task.FromResult(ResolveInternal(connectionStringName)); + } + + private string ResolveInternal(string connectionStringName) { //Get module specific value if provided if (!connectionStringName.IsNullOrEmpty()) @@ -25,9 +37,9 @@ namespace Volo.Abp.Data return moduleConnString; } } - + //Get default value return Options.ConnectionStrings.Default; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringResolver.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringResolver.cs index e9344ef66a..3bc8e22d78 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringResolver.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringResolver.cs @@ -1,10 +1,16 @@ -using JetBrains.Annotations; +using System; +using System.Threading.Tasks; +using JetBrains.Annotations; namespace Volo.Abp.Data { public interface IConnectionStringResolver { [NotNull] + [Obsolete("Use ResolveAsync method.")] string Resolve(string connectionStringName = null); + + [NotNull] + Task ResolveAsync(string connectionStringName = null); } } diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringResolverExtensions.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringResolverExtensions.cs index e3a89e24e8..1fa097964c 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringResolverExtensions.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringResolverExtensions.cs @@ -1,10 +1,22 @@ -namespace Volo.Abp.Data +using System; +using System.Threading.Tasks; +using JetBrains.Annotations; + +namespace Volo.Abp.Data { public static class ConnectionStringResolverExtensions { + [NotNull] + [Obsolete("Use ResolveAsync method")] public static string Resolve(this IConnectionStringResolver resolver) { return resolver.Resolve(ConnectionStringNameAttribute.GetConnStringName()); } + + [NotNull] + public static Task ResolveAsync(this IConnectionStringResolver resolver) + { + return resolver.ResolveAsync(ConnectionStringNameAttribute.GetConnStringName()); + } } } diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyCrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyCrudAppService.cs index 91879f030e..0cfb8ceb24 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyCrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyCrudAppService.cs @@ -132,7 +132,7 @@ namespace Volo.Abp.Application.Services } /// - /// Maps to to create a new entity. + /// Maps to to create a new entity. /// It uses by default. /// It can be overriden for custom mapping. /// Overriding this has higher priority than overriding the @@ -143,7 +143,7 @@ namespace Volo.Abp.Application.Services } /// - /// Maps to to create a new entity. + /// Maps to to create a new entity. /// It uses by default. /// It can be overriden for custom mapping. /// @@ -155,7 +155,7 @@ namespace Volo.Abp.Application.Services } /// - /// Sets Id value for the entity if is . + /// Sets Id value for the entity if is . /// It's used while creating a new entity. /// protected virtual void SetIdForGuids(TEntity entity) @@ -171,7 +171,7 @@ namespace Volo.Abp.Application.Services } /// - /// Maps to to update the entity. + /// Maps to to update the entity. /// It uses by default. /// It can be overriden for custom mapping. /// Overriding this has higher priority than overriding the @@ -183,7 +183,7 @@ namespace Volo.Abp.Application.Services } /// - /// Maps to to update the entity. + /// Maps to to update the entity. /// It uses by default. /// It can be overriden for custom mapping. /// diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyReadOnlyAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyReadOnlyAppService.cs index b9ffe3359b..54123bc843 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyReadOnlyAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyReadOnlyAppService.cs @@ -62,7 +62,7 @@ namespace Volo.Abp.Application.Services { await CheckGetListPolicyAsync(); - var query = CreateFilteredQuery(input); + var query = await CreateFilteredQueryAsync(input); var totalCount = await AsyncExecuter.CountAsync(query); @@ -160,13 +160,37 @@ namespace Volo.Abp.Application.Services /// methods. /// /// The input. + [Obsolete("Override the CreateFilteredQueryAsync method instead.")] protected virtual IQueryable CreateFilteredQuery(TGetListInput input) { return ReadOnlyRepository; } /// - /// Maps to . + /// This method should create based on given input. + /// It should filter query if needed, but should not do sorting or paging. + /// Sorting should be done in and paging should be done in + /// methods. + /// + /// The input. + protected virtual async Task> CreateFilteredQueryAsync(TGetListInput input) + { + /* If user has overridden the CreateFilteredQuery method, + * we don't want to make breaking change in this point. + */ +#pragma warning disable 618 + var query = CreateFilteredQuery(input); +#pragma warning restore 618 + if (!ReferenceEquals(query, ReadOnlyRepository)) + { + return query; + } + + return await ReadOnlyRepository.GetQueryableAsync(); + } + + /// + /// Maps to . /// It internally calls the by default. /// It can be overriden for custom mapping. /// Overriding this has higher priority than overriding the @@ -177,7 +201,7 @@ namespace Volo.Abp.Application.Services } /// - /// Maps to . + /// Maps to . /// It uses by default. /// It can be overriden for custom mapping. /// @@ -187,7 +211,7 @@ namespace Volo.Abp.Application.Services } /// - /// Maps a list of to objects. + /// Maps a list of to objects. /// It uses method for each item in the list. /// protected virtual async Task> MapToGetListOutputDtosAsync(List entities) @@ -203,7 +227,7 @@ namespace Volo.Abp.Application.Services } /// - /// Maps to . + /// Maps to . /// It internally calls the by default. /// It can be overriden for custom mapping. /// Overriding this has higher priority than overriding the @@ -214,7 +238,7 @@ namespace Volo.Abp.Application.Services } /// - /// Maps to . + /// Maps to . /// It uses by default. /// It can be overriden for custom mapping. /// diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs index 111359d7f3..fffde41ba7 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs @@ -80,12 +80,12 @@ namespace Volo.Abp.Application.Services Repository = repository; } - protected async override Task DeleteByIdAsync(TKey id) + protected override async Task DeleteByIdAsync(TKey id) { await Repository.DeleteAsync(id); } - protected async override Task GetEntityByIdAsync(TKey id) + protected override async Task GetEntityByIdAsync(TKey id) { return await Repository.GetAsync(id); } diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ReadOnlyAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ReadOnlyAppService.cs index c585b2ac38..da3f386fd9 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ReadOnlyAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ReadOnlyAppService.cs @@ -38,7 +38,7 @@ namespace Volo.Abp.Application.Services where TGetOutputDto : IEntityDto where TGetListOutputDto : IEntityDto { - protected new IReadOnlyRepository Repository { get; } + protected IReadOnlyRepository Repository { get; } protected ReadOnlyAppService(IReadOnlyRepository repository) : base(repository) @@ -46,7 +46,7 @@ namespace Volo.Abp.Application.Services Repository = repository; } - protected async override Task GetEntityByIdAsync(TKey id) + protected override async Task GetEntityByIdAsync(TKey id) { return await Repository.GetAsync(id); } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/IAbpCommonDbContextRegistrationOptionsBuilder.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/IAbpCommonDbContextRegistrationOptionsBuilder.cs index 368fa2dc96..53d2f142cd 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/IAbpCommonDbContextRegistrationOptionsBuilder.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/IAbpCommonDbContextRegistrationOptionsBuilder.cs @@ -9,11 +9,11 @@ namespace Volo.Abp.DependencyInjection IServiceCollection Services { get; } /// - /// Registers default repositories for this DbContext. + /// Registers default repositories for this DbContext. /// /// /// Registers repositories only for aggregate root entities by default. - /// set to true to include all entities. + /// set to true to include all entities. /// IAbpCommonDbContextRegistrationOptionsBuilder AddDefaultRepositories(bool includeAllEntities = false); @@ -67,4 +67,4 @@ namespace Volo.Abp.DependencyInjection /// The DbContext type to be replaced IAbpCommonDbContextRegistrationOptionsBuilder ReplaceDbContext(Type otherDbContextType); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyRepository.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyRepository.cs index 499a1e58be..80d1425044 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyRepository.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyRepository.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Linq.Expressions; +using System.Threading.Tasks; using Volo.Abp.Domain.Entities; using Volo.Abp.Linq; @@ -11,9 +12,17 @@ namespace Volo.Abp.Domain.Repositories { IAsyncQueryableExecuter AsyncExecuter { get; } + [Obsolete("Use WithDetailsAsync method.")] IQueryable WithDetails(); + [Obsolete("Use WithDetailsAsync method.")] IQueryable WithDetails(params Expression>[] propertySelectors); + + Task> WithDetailsAsync(); //TODO: CancellationToken + + Task> WithDetailsAsync(params Expression>[] propertySelectors); //TODO: CancellationToken + + Task> GetQueryableAsync(); //TODO: CancellationToken } public interface IReadOnlyRepository : IReadOnlyRepository, IReadOnlyBasicRepository diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryAsyncExtensions.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryAsyncExtensions.cs index f6191a152f..acc1c3a1bd 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryAsyncExtensions.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryAsyncExtensions.cs @@ -12,13 +12,14 @@ namespace Volo.Abp.Domain.Repositories { #region Contains - public static Task ContainsAsync( + public static async Task ContainsAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] T item, CancellationToken cancellationToken = default) where T : class, IEntity { - return repository.AsyncExecuter.ContainsAsync(repository, item, cancellationToken); + var queryable = await repository.GetQueryableAsync(); + return await repository.AsyncExecuter.ContainsAsync(queryable, item, cancellationToken); } #endregion diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs index db0ec2b11c..8781fd9547 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs @@ -17,34 +17,54 @@ namespace Volo.Abp.Domain.Repositories public abstract class RepositoryBase : BasicRepositoryBase, IRepository, IUnitOfWorkManagerAccessor where TEntity : class, IEntity { + [Obsolete("This method will be removed in future versions.")] public virtual Type ElementType => GetQueryable().ElementType; + [Obsolete("This method will be removed in future versions.")] public virtual Expression Expression => GetQueryable().Expression; + [Obsolete("This method will be removed in future versions.")] public virtual IQueryProvider Provider => GetQueryable().Provider; + [Obsolete("Use WithDetailsAsync method.")] public virtual IQueryable WithDetails() { return GetQueryable(); } + [Obsolete("Use WithDetailsAsync method.")] public virtual IQueryable WithDetails(params Expression>[] propertySelectors) { return GetQueryable(); } + public virtual Task> WithDetailsAsync() + { + return GetQueryableAsync(); + } + + public virtual Task> WithDetailsAsync(params Expression>[] propertySelectors) + { + return GetQueryableAsync(); + } + + [Obsolete("This method will be removed in future versions.")] IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } + [Obsolete("This method will be removed in future versions.")] public IEnumerator GetEnumerator() { return GetQueryable().GetEnumerator(); } + [Obsolete("Use GetQueryableAsync method.")] protected abstract IQueryable GetQueryable(); + public abstract Task> GetQueryableAsync(); + public abstract Task FindAsync( Expression> predicate, bool includeDetails = true, @@ -103,8 +123,6 @@ namespace Volo.Abp.Domain.Repositories await DeleteAsync(entity, autoSave, cancellationToken); } - - public async Task DeleteManyAsync([NotNull] IEnumerable ids, bool autoSave = false, CancellationToken cancellationToken = default) { foreach (var id in ids) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EfCoreRepositoryExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EfCoreRepositoryExtensions.cs index 2463062cde..5049a1b61b 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EfCoreRepositoryExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EfCoreRepositoryExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; @@ -7,18 +8,32 @@ namespace Volo.Abp.Domain.Repositories { public static class EfCoreRepositoryExtensions { + [Obsolete("Use GetDbContextAsync method.")] public static DbContext GetDbContext(this IReadOnlyBasicRepository repository) where TEntity : class, IEntity { return repository.ToEfCoreRepository().DbContext; } + public static Task GetDbContextAsync(this IReadOnlyBasicRepository repository) + where TEntity : class, IEntity + { + return repository.ToEfCoreRepository().GetDbContextAsync(); + } + + [Obsolete("Use GetDbSetAsync method.")] public static DbSet GetDbSet(this IReadOnlyBasicRepository repository) where TEntity : class, IEntity { return repository.ToEfCoreRepository().DbSet; } + public static Task> GetDbSetAsync(this IReadOnlyBasicRepository repository) + where TEntity : class, IEntity + { + return repository.ToEfCoreRepository().GetDbSetAsync(); + } + public static IEfCoreRepository ToEfCoreRepository(this IReadOnlyBasicRepository repository) where TEntity : class, IEntity { diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs index ca885bd4fb..a95ec00e34 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs @@ -1,8 +1,6 @@ -using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; -using Nito.AsyncEx; using System; using System.Collections.Generic; using System.Linq; @@ -21,18 +19,41 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore where TDbContext : IEfCoreDbContext where TEntity : class, IEntity { - public virtual DbSet DbSet => DbContext.Set(); + [Obsolete("Use GetDbContextAsync() method.")] + protected virtual TDbContext DbContext => _dbContextProvider.GetDbContext(); + [Obsolete("Use GetDbContextAsync() method.")] DbContext IEfCoreRepository.DbContext => DbContext.As(); - protected virtual TDbContext DbContext => _dbContextProvider.GetDbContext(); + async Task IEfCoreRepository.GetDbContextAsync() + { + return await GetDbContextAsync() as DbContext; + } + + protected virtual Task GetDbContextAsync() + { + return _dbContextProvider.GetDbContextAsync(); + } + + [Obsolete("Use GetDbSetAsync() method.")] + public virtual DbSet DbSet => DbContext.Set(); + + Task> IEfCoreRepository.GetDbSetAsync() + { + return GetDbSetAsync(); + } + + protected async Task> GetDbSetAsync() + { + return (await GetDbContextAsync()).Set(); + } protected virtual AbpEntityOptions AbpEntityOptions => _entityOptionsLazy.Value; private readonly IDbContextProvider _dbContextProvider; private readonly Lazy> _entityOptionsLazy; - public virtual IGuidGenerator GuidGenerator { get; set; } + public IGuidGenerator GuidGenerator { get; set; } public IEfCoreBulkOperationProvider BulkOperationProvider { get; set; } @@ -49,15 +70,17 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore ); } - public async override Task InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) + public override async Task InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) { CheckAndSetId(entity); - var savedEntity = DbSet.Add(entity).Entity; + var dbContext = await GetDbContextAsync(); + + var savedEntity = (await dbContext.Set().AddAsync(entity, GetCancellationToken(cancellationToken))).Entity; if (autoSave) { - await DbContext.SaveChangesAsync(GetCancellationToken(cancellationToken)); + await dbContext.SaveChangesAsync(GetCancellationToken(cancellationToken)); } return savedEntity; @@ -65,7 +88,11 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore public override async Task InsertManyAsync(IEnumerable entities, bool autoSave = false, CancellationToken cancellationToken = default) { - foreach (var entity in entities) + var entityArray = entities.ToArray(); + var dbContext = await GetDbContextAsync(); + cancellationToken = GetCancellationToken(cancellationToken); + + foreach (var entity in entityArray) { CheckAndSetId(entity); } @@ -74,30 +101,32 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore { await BulkOperationProvider.InsertManyAsync( this, - entities, + entityArray, autoSave, cancellationToken ); return; } - await DbSet.AddRangeAsync(entities); + await dbContext.Set().AddRangeAsync(entityArray, cancellationToken); if (autoSave) { - await DbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(cancellationToken); } } - public async override Task UpdateAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) + public override async Task UpdateAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) { - DbContext.Attach(entity); + var dbContext = await GetDbContextAsync(); + + dbContext.Attach(entity); - var updatedEntity = DbContext.Update(entity).Entity; + var updatedEntity = dbContext.Update(entity).Entity; if (autoSave) { - await DbContext.SaveChangesAsync(GetCancellationToken(cancellationToken)); + await dbContext.SaveChangesAsync(GetCancellationToken(cancellationToken)); } return updatedEntity; @@ -105,6 +134,8 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore public override async Task UpdateManyAsync(IEnumerable entities, bool autoSave = false, CancellationToken cancellationToken = default) { + cancellationToken = GetCancellationToken(cancellationToken); + if (BulkOperationProvider != null) { await BulkOperationProvider.UpdateManyAsync( @@ -117,65 +148,76 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore return; } - DbSet.UpdateRange(entities); + var dbContext = await GetDbContextAsync(); + + dbContext.Set().UpdateRange(entities); if (autoSave) { - await DbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(cancellationToken); } } - public async override Task DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) + public override async Task DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) { - DbSet.Remove(entity); + var dbContext = await GetDbContextAsync(); + + dbContext.Set().Remove(entity); if (autoSave) { - await DbContext.SaveChangesAsync(GetCancellationToken(cancellationToken)); + await dbContext.SaveChangesAsync(GetCancellationToken(cancellationToken)); } } public override async Task DeleteManyAsync(IEnumerable entities, bool autoSave = false, CancellationToken cancellationToken = default) { + cancellationToken = GetCancellationToken(cancellationToken); + if (BulkOperationProvider != null) { await BulkOperationProvider.DeleteManyAsync( this, entities, autoSave, - cancellationToken); + cancellationToken + ); return; } - DbSet.RemoveRange(entities); + var dbContext = await GetDbContextAsync(); + + dbContext.RemoveRange(entities); if (autoSave) { - await DbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(cancellationToken); } } - public async override Task> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default) + public override async Task> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default) { return includeDetails - ? await WithDetails().ToListAsync(GetCancellationToken(cancellationToken)) - : await DbSet.ToListAsync(GetCancellationToken(cancellationToken)); + ? await (await WithDetailsAsync()).ToListAsync(GetCancellationToken(cancellationToken)) + : await (await GetDbSetAsync()).ToListAsync(GetCancellationToken(cancellationToken)); } - public async override Task GetCountAsync(CancellationToken cancellationToken = default) + public override async Task GetCountAsync(CancellationToken cancellationToken = default) { - return await DbSet.LongCountAsync(GetCancellationToken(cancellationToken)); + return await (await GetDbSetAsync()).LongCountAsync(GetCancellationToken(cancellationToken)); } - public async override Task> GetPagedListAsync( + public override async Task> GetPagedListAsync( int skipCount, int maxResultCount, string sorting, bool includeDetails = false, CancellationToken cancellationToken = default) { - var queryable = includeDetails ? WithDetails() : DbSet; + var queryable = includeDetails + ? await WithDetailsAsync() + : await GetDbSetAsync(); return await queryable .OrderBy(sorting) @@ -183,44 +225,53 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore .ToListAsync(GetCancellationToken(cancellationToken)); } + [Obsolete("Use GetQueryableAsync method.")] protected override IQueryable GetQueryable() { return DbSet.AsQueryable(); } - protected override Task SaveChangesAsync(CancellationToken cancellationToken) + public override async Task> GetQueryableAsync() + { + return (await GetDbSetAsync()).AsQueryable(); + } + + protected override async Task SaveChangesAsync(CancellationToken cancellationToken) { - return DbContext.SaveChangesAsync(cancellationToken); + await (await GetDbContextAsync()).SaveChangesAsync(cancellationToken); } - public async override Task FindAsync( + public override async Task FindAsync( Expression> predicate, bool includeDetails = true, CancellationToken cancellationToken = default) { return includeDetails - ? await WithDetails() + ? await (await WithDetailsAsync()) .Where(predicate) .SingleOrDefaultAsync(GetCancellationToken(cancellationToken)) - : await DbSet + : await (await GetDbSetAsync()) .Where(predicate) .SingleOrDefaultAsync(GetCancellationToken(cancellationToken)); } - public async override Task DeleteAsync(Expression> predicate, bool autoSave = false, CancellationToken cancellationToken = default) + public override async Task DeleteAsync(Expression> predicate, bool autoSave = false, CancellationToken cancellationToken = default) { - var entities = await GetQueryable() + var dbContext = await GetDbContextAsync(); + var dbSet = dbContext.Set(); + + var entities = await dbSet .Where(predicate) .ToListAsync(GetCancellationToken(cancellationToken)); foreach (var entity in entities) { - DbSet.Remove(entity); + dbSet.Remove(entity); } if (autoSave) { - await DbContext.SaveChangesAsync(GetCancellationToken(cancellationToken)); + await dbContext.SaveChangesAsync(GetCancellationToken(cancellationToken)); } } @@ -230,7 +281,7 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore CancellationToken cancellationToken = default) where TProperty : class { - await DbContext + await (await GetDbContextAsync()) .Entry(entity) .Collection(propertyExpression) .LoadAsync(GetCancellationToken(cancellationToken)); @@ -242,12 +293,13 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore CancellationToken cancellationToken = default) where TProperty : class { - await DbContext + await (await GetDbContextAsync()) .Entry(entity) .Reference(propertyExpression) .LoadAsync(GetCancellationToken(cancellationToken)); } + [Obsolete("Use WithDetailsAsync")] public override IQueryable WithDetails() { if (AbpEntityOptions.DefaultWithDetailsFunc == null) @@ -258,10 +310,37 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore return AbpEntityOptions.DefaultWithDetailsFunc(GetQueryable()); } + public override async Task> WithDetailsAsync() + { + if (AbpEntityOptions.DefaultWithDetailsFunc == null) + { + return await base.WithDetailsAsync(); + } + + return AbpEntityOptions.DefaultWithDetailsFunc(await GetQueryableAsync()); + } + + [Obsolete("Use WithDetailsAsync method.")] public override IQueryable WithDetails(params Expression>[] propertySelectors) { - var query = GetQueryable(); + return IncludeDetails( + GetQueryable(), + propertySelectors + ); + } + public override async Task> WithDetailsAsync(params Expression>[] propertySelectors) + { + return IncludeDetails( + await GetQueryableAsync(), + propertySelectors + ); + } + + private static IQueryable IncludeDetails( + IQueryable query, + Expression>[] propertySelectors) + { if (!propertySelectors.IsNullOrEmpty()) { foreach (var propertySelector in propertySelectors) @@ -273,6 +352,7 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore return query; } + [Obsolete("This method will be deleted in future versions.")] public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { return DbSet.AsAsyncEnumerable().GetAsyncEnumerator(cancellationToken); @@ -329,8 +409,8 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore public virtual async Task FindAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default) { return includeDetails - ? await WithDetails().FirstOrDefaultAsync(e => e.Id.Equals(id), GetCancellationToken(cancellationToken)) - : await DbSet.FindAsync(new object[] { id }, GetCancellationToken(cancellationToken)); + ? await (await WithDetailsAsync()).FirstOrDefaultAsync(e => e.Id.Equals(id), GetCancellationToken(cancellationToken)) + : await (await GetDbSetAsync()).FindAsync(new object[] {id}, GetCancellationToken(cancellationToken)); } public virtual async Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default) @@ -344,9 +424,11 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore await DeleteAsync(entity, autoSave, cancellationToken); } - public async virtual Task DeleteManyAsync([NotNull] IEnumerable ids, bool autoSave = false, CancellationToken cancellationToken = default) + public virtual async Task DeleteManyAsync(IEnumerable ids, bool autoSave = false, CancellationToken cancellationToken = default) { - var entities = await DbSet.Where(x => ids.Contains(x.Id)).ToListAsync(); + cancellationToken = GetCancellationToken(cancellationToken); + + var entities = await (await GetDbSetAsync()).Where(x => ids.Contains(x.Id)).ToListAsync(cancellationToken); await DeleteManyAsync(entities, autoSave, cancellationToken); } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/IEfCoreRepository.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/IEfCoreRepository.cs index 31a78f744d..f793dc04ed 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/IEfCoreRepository.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/IEfCoreRepository.cs @@ -1,3 +1,5 @@ +using System; +using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Volo.Abp.Domain.Entities; @@ -6,9 +8,15 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore public interface IEfCoreRepository : IRepository where TEntity : class, IEntity { + [Obsolete("Use GetDbContextAsync() method.")] DbContext DbContext { get; } + [Obsolete("Use GetDbSetAsync() method.")] DbSet DbSet { get; } + + Task GetDbContextAsync(); + + Task> GetDbSetAsync(); } public interface IEfCoreRepository : IEfCoreRepository, IRepository @@ -16,4 +24,4 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore { } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/DbContextOptionsFactory.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/DbContextOptionsFactory.cs index a2d52eac48..0147de12fb 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/DbContextOptionsFactory.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/DbContextOptionsFactory.cs @@ -86,7 +86,11 @@ namespace Volo.Abp.EntityFrameworkCore.DependencyInjection } var connectionStringName = ConnectionStringNameAttribute.GetConnStringName(); + + //Use DefaultConnectionStringResolver.Resolve when we remove IConnectionStringResolver.Resolve +#pragma warning disable 618 var connectionString = serviceProvider.GetRequiredService().Resolve(connectionStringName); +#pragma warning restore 618 return new DbContextCreationContext( connectionStringName, diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider.cs index 68ff261588..2a0400c578 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider.cs @@ -11,7 +11,7 @@ using Volo.Abp.Linq; namespace Volo.Abp.EntityFrameworkCore { - public class EfCoreAsyncQueryableProvider : IAsyncQueryableProvider, ITransientDependency + public class EfCoreAsyncQueryableProvider : IAsyncQueryableProvider, ISingletonDependency { public bool CanExecute(IQueryable queryable) { diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/IDbContextProvider.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/IDbContextProvider.cs index c4655fddd0..b35436cfbc 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/IDbContextProvider.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/IDbContextProvider.cs @@ -1,8 +1,14 @@ +using System; +using System.Threading.Tasks; + namespace Volo.Abp.EntityFrameworkCore { - public interface IDbContextProvider + public interface IDbContextProvider where TDbContext : IEfCoreDbContext { + [Obsolete("Use GetDbContextAsync method.")] TDbContext GetDbContext(); + + Task GetDbContextAsync(); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/ObjectExtending/EfCoreObjectExtensionManagerExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/ObjectExtending/EfCoreObjectExtensionManagerExtensions.cs index 14fcc93784..54c1909bb3 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/ObjectExtending/EfCoreObjectExtensionManagerExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/ObjectExtending/EfCoreObjectExtensionManagerExtensions.cs @@ -143,7 +143,9 @@ namespace Volo.Abp.ObjectExtending var propertyBuilder = typeBuilder.Property(property.Type, property.Name); efCoreMapping.EntityTypeAndPropertyBuildAction?.Invoke(typeBuilder, propertyBuilder); +#pragma warning disable 618 efCoreMapping.PropertyBuildAction?.Invoke(propertyBuilder); +#pragma warning restore 618 } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/UnitOfWorkDbContextProvider.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/UnitOfWorkDbContextProvider.cs index 91ed2f8126..143a5659cc 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/UnitOfWorkDbContextProvider.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/UnitOfWorkDbContextProvider.cs @@ -1,11 +1,15 @@ using System; +using System.Threading; +using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.DependencyInjection; +using Volo.Abp.Threading; namespace Volo.Abp.Uow.EntityFrameworkCore { @@ -14,19 +18,34 @@ namespace Volo.Abp.Uow.EntityFrameworkCore public class UnitOfWorkDbContextProvider : IDbContextProvider where TDbContext : IEfCoreDbContext { + public ILogger> Logger { get; set; } + private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IConnectionStringResolver _connectionStringResolver; + private readonly ICancellationTokenProvider _cancellationTokenProvider; public UnitOfWorkDbContextProvider( IUnitOfWorkManager unitOfWorkManager, - IConnectionStringResolver connectionStringResolver) + IConnectionStringResolver connectionStringResolver, + ICancellationTokenProvider cancellationTokenProvider) { _unitOfWorkManager = unitOfWorkManager; _connectionStringResolver = connectionStringResolver; + _cancellationTokenProvider = cancellationTokenProvider; + + Logger = NullLogger>.Instance; } + [Obsolete("Use GetDbContextAsync method.")] public TDbContext GetDbContext() { + Logger.LogWarning( + "UnitOfWorkDbContextProvider.GetDbContext is deprecated. Use GetDbContextAsync instead! " + + "You are probably using LINQ (LINQ extensions) directly on a repository. In this case, use repository.GetQueryableAsync() method " + + "to obtain an IQueryable instance and use LINQ (LINQ extensions) on this object. " + ); + Logger.LogWarning(Environment.StackTrace.Truncate(2048)); + var unitOfWork = _unitOfWorkManager.Current; if (unitOfWork == null) { @@ -47,6 +66,33 @@ namespace Volo.Abp.Uow.EntityFrameworkCore return ((EfCoreDatabaseApi)databaseApi).DbContext; } + public async Task GetDbContextAsync() + { + var unitOfWork = _unitOfWorkManager.Current; + if (unitOfWork == null) + { + throw new AbpException("A DbContext can only be created inside a unit of work!"); + } + + var connectionStringName = ConnectionStringNameAttribute.GetConnStringName(); + var connectionString = await _connectionStringResolver.ResolveAsync(connectionStringName); + + var dbContextKey = $"{typeof(TDbContext).FullName}_{connectionString}"; + + var databaseApi = unitOfWork.FindDatabaseApi(dbContextKey); + + if (databaseApi == null) + { + databaseApi = new EfCoreDatabaseApi( + await CreateDbContextAsync(unitOfWork, connectionStringName, connectionString) + ); + + unitOfWork.AddDatabaseApi(dbContextKey, databaseApi); + } + + return ((EfCoreDatabaseApi)databaseApi).DbContext; + } + private TDbContext CreateDbContext(IUnitOfWork unitOfWork, string connectionStringName, string connectionString) { var creationContext = new DbContextCreationContext(connectionStringName, connectionString); @@ -67,6 +113,26 @@ namespace Volo.Abp.Uow.EntityFrameworkCore } } + private async Task CreateDbContextAsync(IUnitOfWork unitOfWork, string connectionStringName, string connectionString) + { + var creationContext = new DbContextCreationContext(connectionStringName, connectionString); + using (DbContextCreationContext.Use(creationContext)) + { + var dbContext = await CreateDbContextAsync(unitOfWork); + + if (dbContext is IAbpEfCoreDbContext abpEfCoreDbContext) + { + abpEfCoreDbContext.Initialize( + new AbpEfCoreDbContextInitializationContext( + unitOfWork + ) + ); + } + + return dbContext; + } + } + private TDbContext CreateDbContext(IUnitOfWork unitOfWork) { return unitOfWork.Options.IsTransactional @@ -74,7 +140,16 @@ namespace Volo.Abp.Uow.EntityFrameworkCore : unitOfWork.ServiceProvider.GetRequiredService(); } - public TDbContext CreateDbContextWithTransaction(IUnitOfWork unitOfWork) + private async Task CreateDbContextAsync(IUnitOfWork unitOfWork) + { + Logger.LogDebug($"Creating a new DbContext of type {typeof(TDbContext).FullName}"); + + return unitOfWork.Options.IsTransactional + ? await CreateDbContextWithTransactionAsync(unitOfWork) + : unitOfWork.ServiceProvider.GetRequiredService(); + } + + private TDbContext CreateDbContextWithTransaction(IUnitOfWork unitOfWork) { var transactionApiKey = $"EntityFrameworkCore_{DbContextCreationContext.Current.ConnectionString}"; var activeTransaction = unitOfWork.FindTransactionApi(transactionApiKey) as EfCoreTransactionApi; @@ -117,5 +192,54 @@ namespace Volo.Abp.Uow.EntityFrameworkCore return dbContext; } } + + private async Task CreateDbContextWithTransactionAsync(IUnitOfWork unitOfWork) + { + var transactionApiKey = $"EntityFrameworkCore_{DbContextCreationContext.Current.ConnectionString}"; + var activeTransaction = unitOfWork.FindTransactionApi(transactionApiKey) as EfCoreTransactionApi; + + if (activeTransaction == null) + { + var dbContext = unitOfWork.ServiceProvider.GetRequiredService(); + + var dbTransaction = unitOfWork.Options.IsolationLevel.HasValue + ? await dbContext.Database.BeginTransactionAsync(unitOfWork.Options.IsolationLevel.Value, GetCancellationToken()) + : await dbContext.Database.BeginTransactionAsync(GetCancellationToken()); + + unitOfWork.AddTransactionApi( + transactionApiKey, + new EfCoreTransactionApi( + dbTransaction, + dbContext + ) + ); + + return dbContext; + } + else + { + DbContextCreationContext.Current.ExistingConnection = activeTransaction.DbContextTransaction.GetDbTransaction().Connection; + + var dbContext = unitOfWork.ServiceProvider.GetRequiredService(); + + if (dbContext.As().HasRelationalTransactionManager()) + { + await dbContext.Database.UseTransactionAsync(activeTransaction.DbContextTransaction.GetDbTransaction(), GetCancellationToken()); + } + else + { + await dbContext.Database.BeginTransactionAsync(GetCancellationToken()); //TODO: Why not using the new created transaction? + } + + activeTransaction.AttendedDbContexts.Add(dbContext); + + return dbContext; + } + } + + protected virtual CancellationToken GetCancellationToken(CancellationToken preferredValue = default) + { + return _cancellationTokenProvider.FallbackToProvider(preferredValue); + } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventBus.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventBus.cs index 1d93c05580..d28b3ab2a4 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventBus.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventBus.cs @@ -33,7 +33,7 @@ namespace Volo.Abp.EventBus /// /// Registers to an event. - /// A new instance of object is created for every event occurrence. + /// A new instance of object is created for every event occurrence. /// /// Event type /// Type of the event handler @@ -116,4 +116,4 @@ namespace Volo.Abp.EventBus /// Event type void UnsubscribeAll(Type eventType); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventDataMayHaveTenantId.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventDataMayHaveTenantId.cs index 72a8c753cd..9ff8b89cd8 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventDataMayHaveTenantId.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventDataMayHaveTenantId.cs @@ -16,8 +16,8 @@ namespace Volo.Abp.EventBus { /// /// Returns true if this event data has a Tenant Id information. - /// If so, it should set the our parameter. - /// Otherwise, the our parameter value should not be informative + /// If so, it should set the our parameter. + /// Otherwise, the our parameter value should not be informative /// (it will be null as expected, but doesn't indicate a tenant with null tenant id). /// /// diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureDefinition.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureDefinition.cs index b2b11f0a18..609f42acd2 100644 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureDefinition.cs +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureDefinition.cs @@ -69,8 +69,8 @@ namespace Volo.Abp.Features /// /// Name of the property /// - /// Returns the value in the dictionary by given . - /// Returns null if given is not present in the dictionary. + /// Returns the value in the dictionary by given . + /// Returns null if given is not present in the dictionary. /// [CanBeNull] public object this[string name] diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureGroupDefinition.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureGroupDefinition.cs index cba38070a7..b4dd98eb5b 100644 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureGroupDefinition.cs +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureGroupDefinition.cs @@ -29,8 +29,8 @@ namespace Volo.Abp.Features /// /// Name of the property /// - /// Returns the value in the dictionary by given . - /// Returns null if given is not present in the dictionary. + /// Returns the value in the dictionary by given . + /// Returns null if given is not present in the dictionary. /// public object this[string name] { @@ -39,7 +39,7 @@ namespace Volo.Abp.Features } protected internal FeatureGroupDefinition( - string name, + string name, ILocalizableString displayName = null) { Name = name; @@ -108,4 +108,4 @@ namespace Volo.Abp.Features return $"[{nameof(FeatureGroupDefinition)} {Name}]"; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbRepository.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbRepository.cs index c179b68931..6d4fb7d896 100644 --- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbRepository.cs +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbRepository.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Threading.Tasks; using Volo.Abp.Domain.Entities; namespace Volo.Abp.Domain.Repositories.MemoryDb @@ -6,9 +7,15 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb public interface IMemoryDbRepository : IRepository where TEntity : class, IEntity { + [Obsolete("Use GetDatabaseAsync() method.")] IMemoryDatabase Database { get; } + [Obsolete("Use GetCollectionAsync() method.")] IMemoryDatabaseCollection Collection { get; } + + Task GetDatabaseAsync(); + + Task> GetCollectionAsync(); } public interface IMemoryDbRepository : IMemoryDbRepository, IRepository diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs index 7c67e254ee..811c51ed5f 100644 --- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs @@ -1,4 +1,3 @@ -using JetBrains.Annotations; using System; using System.Collections.Generic; using System.Linq; @@ -22,10 +21,22 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb { //TODO: Add dbcontext just like mongodb implementation! + [Obsolete("Use GetCollectionAsync method.")] public virtual IMemoryDatabaseCollection Collection => Database.Collection(); + public async Task> GetCollectionAsync() + { + return (await GetDatabaseAsync()).Collection(); + } + + [Obsolete("Use GetDatabaseAsync method.")] public virtual IMemoryDatabase Database => DatabaseProvider.GetDatabase(); + public Task GetDatabaseAsync() + { + return DatabaseProvider.GetDatabaseAsync(); + } + protected IMemoryDatabaseProvider DatabaseProvider { get; } public ILocalEventBus LocalEventBus { get; set; } @@ -47,11 +58,17 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb EntityChangeEventHelper = NullEntityChangeEventHelper.Instance; } + [Obsolete("This method will be removed in future versions.")] protected override IQueryable GetQueryable() { return ApplyDataFilters(Collection.AsQueryable()); } + public override async Task> GetQueryableAsync() + { + return ApplyDataFilters((await GetCollectionAsync()).AsQueryable()); + } + protected virtual async Task TriggerDomainEventsAsync(object entity) { var generatesDomainEventsEntity = entity as IGeneratesDomainEvents; @@ -163,39 +180,40 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb await TriggerDomainEventsAsync(entity); } - public override Task FindAsync( + public override async Task FindAsync( Expression> predicate, bool includeDetails = true, CancellationToken cancellationToken = default) { - return Task.FromResult(GetQueryable().Where(predicate).SingleOrDefault()); + return (await GetQueryableAsync()).Where(predicate).SingleOrDefault(); } - public async override Task DeleteAsync( + public override async Task DeleteAsync( Expression> predicate, bool autoSave = false, CancellationToken cancellationToken = default) { - var entities = GetQueryable().Where(predicate).ToList(); + var entities = (await GetQueryableAsync()).Where(predicate).ToList(); + foreach (var entity in entities) { await DeleteAsync(entity, autoSave, cancellationToken); } } - public async override Task InsertAsync( + public override async Task InsertAsync( TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) { await ApplyAbpConceptsForAddedEntityAsync(entity); - Collection.Add(entity); + (await GetCollectionAsync()).Add(entity); return entity; } - public async override Task UpdateAsync( + public override async Task UpdateAsync( TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) @@ -214,12 +232,12 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb await TriggerDomainEventsAsync(entity); - Collection.Update(entity); + (await GetCollectionAsync()).Update(entity); return entity; } - public async override Task DeleteAsync( + public override async Task DeleteAsync( TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) @@ -229,35 +247,35 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb if (entity is ISoftDelete softDeleteEntity && !IsHardDeleted(entity)) { softDeleteEntity.IsDeleted = true; - Collection.Update(entity); + (await GetCollectionAsync()).Update(entity); } else { - Collection.Remove(entity); + (await GetCollectionAsync()).Remove(entity); } } - public override Task> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default) + public override async Task> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default) { - return Task.FromResult(GetQueryable().ToList()); + return (await GetQueryableAsync()).ToList(); } - public override Task GetCountAsync(CancellationToken cancellationToken = default) + public override async Task GetCountAsync(CancellationToken cancellationToken = default) { - return Task.FromResult(GetQueryable().LongCount()); + return (await GetQueryableAsync()).LongCount(); } - public override Task> GetPagedListAsync( + public override async Task> GetPagedListAsync( int skipCount, int maxResultCount, string sorting, bool includeDetails = false, CancellationToken cancellationToken = default) { - return Task.FromResult(GetQueryable() + return (await GetQueryableAsync()) .OrderBy(sorting) .PageBy(skipCount, maxResultCount) - .ToList()); + .ToList(); } } @@ -270,13 +288,13 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb { } - public override Task InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) + public override async Task InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) { - SetIdIfNeeded(entity); - return base.InsertAsync(entity, autoSave, cancellationToken); + await SetIdIfNeededAsync(entity); + return await base.InsertAsync(entity, autoSave, cancellationToken); } - protected virtual void SetIdIfNeeded(TEntity entity) + protected virtual async Task SetIdIfNeededAsync(TEntity entity) { if (typeof(TKey) == typeof(int) || typeof(TKey) == typeof(long) || @@ -284,7 +302,8 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb { if (EntityHelper.HasDefaultId(entity)) { - EntityHelper.TrySetId(entity, () => Database.GenerateNextId()); + var nextId = (await GetDatabaseAsync()).GenerateNextId(); + EntityHelper.TrySetId(entity, () => nextId); } } } @@ -301,9 +320,9 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb return entity; } - public virtual Task FindAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task FindAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default) { - return Task.FromResult(GetQueryable().FirstOrDefault(e => e.Id.Equals(id))); + return (await GetQueryableAsync()).FirstOrDefault(e => e.Id.Equals(id)); } public virtual async Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default) @@ -311,10 +330,10 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb await DeleteAsync(x => x.Id.Equals(id), autoSave, cancellationToken); } - public virtual async Task DeleteManyAsync([NotNull] IEnumerable ids, bool autoSave = false, CancellationToken cancellationToken = default) + public virtual async Task DeleteManyAsync(IEnumerable ids, bool autoSave = false, CancellationToken cancellationToken = default) { - var entities = await AsyncExecuter.ToListAsync(GetQueryable().Where(x => ids.Contains(x.Id))); - DeleteManyAsync(entities, autoSave, cancellationToken); + var entities = await AsyncExecuter.ToListAsync((await GetQueryableAsync()).Where(x => ids.Contains(x.Id)), cancellationToken); + await DeleteManyAsync(entities, autoSave, cancellationToken); } } } diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDbCoreRepositoryExtensions.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDbCoreRepositoryExtensions.cs index 1547a581e5..003bf8b034 100644 --- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDbCoreRepositoryExtensions.cs +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDbCoreRepositoryExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories.MemoryDb; @@ -7,18 +8,32 @@ namespace Volo.Abp.Domain.Repositories { public static class MemoryDbCoreRepositoryExtensions { + [Obsolete("Use GetDatabaseAsync method.")] public static IMemoryDatabase GetDatabase(this IBasicRepository repository) where TEntity : class, IEntity { return repository.ToMemoryDbRepository().Database; } + public static Task GetDatabaseAsync(this IBasicRepository repository) + where TEntity : class, IEntity + { + return repository.ToMemoryDbRepository().GetDatabaseAsync(); + } + + [Obsolete("Use GetCollectionAsync method.")] public static IMemoryDatabaseCollection GetCollection(this IBasicRepository repository) where TEntity : class, IEntity { return repository.ToMemoryDbRepository().Collection; } + public static Task> GetCollectionAsync(this IBasicRepository repository) + where TEntity : class, IEntity + { + return repository.ToMemoryDbRepository().GetCollectionAsync(); + } + public static IMemoryDbRepository ToMemoryDbRepository(this IBasicRepository repository) where TEntity : class, IEntity { @@ -31,4 +46,4 @@ namespace Volo.Abp.Domain.Repositories return memoryDbRepository; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/MemoryDb/IMemoryDatabaseProvider.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/MemoryDb/IMemoryDatabaseProvider.cs index ad4456c793..514b079e69 100644 --- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/MemoryDb/IMemoryDatabaseProvider.cs +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/MemoryDb/IMemoryDatabaseProvider.cs @@ -1,12 +1,20 @@ -using Volo.Abp.Domain.Repositories.MemoryDb; +using System; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories.MemoryDb; namespace Volo.Abp.MemoryDb { public interface IMemoryDatabaseProvider where TMemoryDbContext : MemoryDbContext { + [Obsolete("Use GetDbContextAsync method.")] TMemoryDbContext DbContext { get; } + Task GetDbContextAsync(); + + [Obsolete("Use GetDatabaseAsync method.")] IMemoryDatabase GetDatabase(); + + Task GetDatabaseAsync(); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Uow/MemoryDb/UnitOfWorkMemoryDatabaseProvider.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Uow/MemoryDb/UnitOfWorkMemoryDatabaseProvider.cs index 24c1cdaeb9..c2c5a1df71 100644 --- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Uow/MemoryDb/UnitOfWorkMemoryDatabaseProvider.cs +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Uow/MemoryDb/UnitOfWorkMemoryDatabaseProvider.cs @@ -1,4 +1,6 @@ -using Volo.Abp.Data; +using System; +using System.Threading.Tasks; +using Volo.Abp.Data; using Volo.Abp.Domain.Repositories.MemoryDb; using Volo.Abp.MemoryDb; @@ -8,7 +10,7 @@ namespace Volo.Abp.Uow.MemoryDb where TMemoryDbContext : MemoryDbContext { public TMemoryDbContext DbContext { get; } - + private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IConnectionStringResolver _connectionStringResolver; private readonly MemoryDatabaseManager _memoryDatabaseManager; @@ -16,7 +18,7 @@ namespace Volo.Abp.Uow.MemoryDb public UnitOfWorkMemoryDatabaseProvider( IUnitOfWorkManager unitOfWorkManager, IConnectionStringResolver connectionStringResolver, - TMemoryDbContext dbContext, + TMemoryDbContext dbContext, MemoryDatabaseManager memoryDatabaseManager) { _unitOfWorkManager = unitOfWorkManager; @@ -25,6 +27,12 @@ namespace Volo.Abp.Uow.MemoryDb _memoryDatabaseManager = memoryDatabaseManager; } + public Task GetDbContextAsync() + { + return Task.FromResult(DbContext); + } + + [Obsolete("Use GetDatabaseAsync method.")] public IMemoryDatabase GetDatabase() { var unitOfWork = _unitOfWorkManager.Current; @@ -44,5 +52,25 @@ namespace Volo.Abp.Uow.MemoryDb return ((MemoryDbDatabaseApi)databaseApi).Database; } + + public async Task GetDatabaseAsync() + { + var unitOfWork = _unitOfWorkManager.Current; + if (unitOfWork == null) + { + throw new AbpException($"A {nameof(IMemoryDatabase)} instance can only be created inside a unit of work!"); + } + + var connectionString = await _connectionStringResolver.ResolveAsync(); + var dbContextKey = $"{typeof(TMemoryDbContext).FullName}_{connectionString}"; + + var databaseApi = unitOfWork.GetOrAddDatabaseApi( + dbContextKey, + () => new MemoryDbDatabaseApi( + _memoryDatabaseManager.Get(connectionString) + )); + + return ((MemoryDbDatabaseApi)databaseApi).Database; + } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs index 50155c6df5..960222679f 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs @@ -1,4 +1,7 @@ -using MongoDB.Driver; +using System; +using System.Threading; +using System.Threading.Tasks; +using MongoDB.Driver; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Entities; @@ -7,11 +10,20 @@ namespace Volo.Abp.Domain.Repositories.MongoDB public interface IMongoDbRepository : IRepository where TEntity : class, IEntity { + [Obsolete("Use GetDatabaseAsync method.")] IMongoDatabase Database { get; } + Task GetDatabaseAsync(CancellationToken cancellationToken = default); + + [Obsolete("Use GetCollectionAsync method.")] IMongoCollection Collection { get; } + Task> GetCollectionAsync(CancellationToken cancellationToken = default); + + [Obsolete("Use GetMongoQueryableAsync method.")] IMongoQueryable GetMongoQueryable(); + + Task> GetMongoQueryableAsync(CancellationToken cancellationToken = default); } public interface IMongoDbRepository : IMongoDbRepository, IRepository diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs index 109aeac8cd..53c291a178 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs @@ -27,13 +27,37 @@ namespace Volo.Abp.Domain.Repositories.MongoDB where TMongoDbContext : IAbpMongoDbContext where TEntity : class, IEntity { + [Obsolete("Use GetCollectionAsync method.")] public virtual IMongoCollection Collection => DbContext.Collection(); + public async Task> GetCollectionAsync(CancellationToken cancellationToken = default) + { + return (await GetDbContextAsync(GetCancellationToken(cancellationToken))).Collection(); + } + + [Obsolete("Use GetDatabaseAsync method.")] public virtual IMongoDatabase Database => DbContext.Database; - public virtual IClientSessionHandle SessionHandle => DbContext.SessionHandle; + public async Task GetDatabaseAsync(CancellationToken cancellationToken = default) + { + return (await GetDbContextAsync(GetCancellationToken(cancellationToken))).Database; + } + + [Obsolete("Use GetSessionHandleAsync method.")] + protected virtual IClientSessionHandle SessionHandle => DbContext.SessionHandle; - public virtual TMongoDbContext DbContext => DbContextProvider.GetDbContext(); + protected async Task GetSessionHandleAsync(CancellationToken cancellationToken = default) + { + return (await GetDbContextAsync(GetCancellationToken(cancellationToken))).SessionHandle; + } + + [Obsolete("Use GetDbContextAsync method.")] + protected virtual TMongoDbContext DbContext => DbContextProvider.GetDbContext(); + + protected Task GetDbContextAsync(CancellationToken cancellationToken = default) + { + return DbContextProvider.GetDbContextAsync(GetCancellationToken(cancellationToken)); + } protected IMongoDbContextProvider DbContextProvider { get; } @@ -59,24 +83,27 @@ namespace Volo.Abp.Domain.Repositories.MongoDB GuidGenerator = SimpleGuidGenerator.Instance; } - public async override Task InsertAsync( + public override async Task InsertAsync( TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) { await ApplyAbpConceptsForAddedEntityAsync(entity); - if (SessionHandle != null) + var dbContext = await GetDbContextAsync(GetCancellationToken(cancellationToken)); + var collection = dbContext.Collection(); + + if (dbContext.SessionHandle != null) { - await Collection.InsertOneAsync( - SessionHandle, + await collection.InsertOneAsync( + dbContext.SessionHandle, entity, cancellationToken: GetCancellationToken(cancellationToken) ); } else { - await Collection.InsertOneAsync( + await collection.InsertOneAsync( entity, cancellationToken: GetCancellationToken(cancellationToken) ); @@ -87,33 +114,38 @@ namespace Volo.Abp.Domain.Repositories.MongoDB public override async Task InsertManyAsync(IEnumerable entities, bool autoSave = false, CancellationToken cancellationToken = default) { - foreach (var entity in entities) + var entityArray = entities.ToArray(); + + foreach (var entity in entityArray) { await ApplyAbpConceptsForAddedEntityAsync(entity); } + var dbContext = await GetDbContextAsync(GetCancellationToken(cancellationToken)); + var collection = dbContext.Collection(); + if (BulkOperationProvider != null) { - await BulkOperationProvider.InsertManyAsync(this, entities, SessionHandle, autoSave, cancellationToken); + await BulkOperationProvider.InsertManyAsync(this, entityArray, dbContext.SessionHandle, autoSave, cancellationToken); return; } - if (SessionHandle != null) + if (dbContext.SessionHandle != null) { - await Collection.InsertManyAsync( - SessionHandle, - entities, + await collection.InsertManyAsync( + dbContext.SessionHandle, + entityArray, cancellationToken: cancellationToken); } else { - await Collection.InsertManyAsync( - entities, + await collection.InsertManyAsync( + entityArray, cancellationToken: cancellationToken); } } - public async override Task UpdateAsync( + public override async Task UpdateAsync( TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) @@ -135,20 +167,21 @@ namespace Volo.Abp.Domain.Repositories.MongoDB var oldConcurrencyStamp = SetNewConcurrencyStamp(entity); ReplaceOneResult result; - if (SessionHandle != null) + var dbContext = await GetDbContextAsync(GetCancellationToken(cancellationToken)); + var collection = dbContext.Collection(); + + if (dbContext.SessionHandle != null) { - result = await Collection.ReplaceOneAsync( - SessionHandle, + result = await collection.ReplaceOneAsync( + dbContext.SessionHandle, CreateEntityFilter(entity, true, oldConcurrencyStamp), entity, cancellationToken: GetCancellationToken(cancellationToken) ); - - } else { - result = await Collection.ReplaceOneAsync( + result = await collection.ReplaceOneAsync( CreateEntityFilter(entity, true, oldConcurrencyStamp), entity, cancellationToken: GetCancellationToken(cancellationToken) @@ -165,12 +198,13 @@ namespace Volo.Abp.Domain.Repositories.MongoDB public override async Task UpdateManyAsync(IEnumerable entities, bool autoSave = false, CancellationToken cancellationToken = default) { - var isSoftDeleteEntity = typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)); + var entityArray = entities.ToArray(); - foreach (var entity in entities) + foreach (var entity in entityArray) { SetModificationAuditProperties(entity); + var isSoftDeleteEntity = typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)); if (isSoftDeleteEntity) { SetDeletionAuditProperties(entity); @@ -186,37 +220,40 @@ namespace Volo.Abp.Domain.Repositories.MongoDB SetNewConcurrencyStamp(entity); } + cancellationToken = GetCancellationToken(cancellationToken); + var dbContext = await GetDbContextAsync(cancellationToken); + if (BulkOperationProvider != null) { - await BulkOperationProvider.UpdateManyAsync(this, entities, SessionHandle, autoSave, cancellationToken); + await BulkOperationProvider.UpdateManyAsync(this, entityArray, dbContext.SessionHandle, autoSave, cancellationToken); return; } - var entitiesCount = entities.Count(); BulkWriteResult result; List> replaceRequests = new List>(); - foreach (var entity in entities) + foreach (var entity in entityArray) { replaceRequests.Add(new ReplaceOneModel(CreateEntityFilter(entity), entity)); } - if (SessionHandle != null) + var collection = dbContext.Collection(); + if (dbContext.SessionHandle != null) { - result = await Collection.BulkWriteAsync(SessionHandle, replaceRequests); + result = await collection.BulkWriteAsync(dbContext.SessionHandle, replaceRequests, cancellationToken: cancellationToken); } else { - result = await Collection.BulkWriteAsync(replaceRequests); + result = await collection.BulkWriteAsync(replaceRequests, cancellationToken: cancellationToken); } - if (result.MatchedCount < entitiesCount) + if (result.MatchedCount < entityArray.Length) { ThrowOptimisticConcurrencyException(); } } - public async override Task DeleteAsync( + public override async Task DeleteAsync( TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) @@ -224,15 +261,18 @@ namespace Volo.Abp.Domain.Repositories.MongoDB await ApplyAbpConceptsForDeletedEntityAsync(entity); var oldConcurrencyStamp = SetNewConcurrencyStamp(entity); + var dbContext = await GetDbContextAsync(GetCancellationToken(cancellationToken)); + var collection = dbContext.Collection(); + if (entity is ISoftDelete softDeleteEntity && !IsHardDeleted(entity)) { softDeleteEntity.IsDeleted = true; ReplaceOneResult result; - if (SessionHandle != null) + if (dbContext.SessionHandle != null) { - result = await Collection.ReplaceOneAsync( - SessionHandle, + result = await collection.ReplaceOneAsync( + dbContext.SessionHandle, CreateEntityFilter(entity, true, oldConcurrencyStamp), entity, cancellationToken: GetCancellationToken(cancellationToken) @@ -240,7 +280,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB } else { - result = await Collection.ReplaceOneAsync( + result = await collection.ReplaceOneAsync( CreateEntityFilter(entity, true, oldConcurrencyStamp), entity, cancellationToken: GetCancellationToken(cancellationToken) @@ -256,17 +296,17 @@ namespace Volo.Abp.Domain.Repositories.MongoDB { DeleteResult result; - if (SessionHandle != null) + if (dbContext.SessionHandle != null) { - result = await Collection.DeleteOneAsync( - SessionHandle, + result = await collection.DeleteOneAsync( + dbContext.SessionHandle, CreateEntityFilter(entity, true, oldConcurrencyStamp), cancellationToken: GetCancellationToken(cancellationToken) ); } else { - result = await Collection.DeleteOneAsync( + result = await collection.DeleteOneAsync( CreateEntityFilter(entity, true, oldConcurrencyStamp), GetCancellationToken(cancellationToken) ); @@ -284,35 +324,40 @@ namespace Volo.Abp.Domain.Repositories.MongoDB bool autoSave = false, CancellationToken cancellationToken = default) { - foreach (var entity in entities) + var entityArray = entities.ToArray(); + + foreach (var entity in entityArray) { await ApplyAbpConceptsForDeletedEntityAsync(entity); - var oldConcurrencyStamp = SetNewConcurrencyStamp(entity); + SetNewConcurrencyStamp(entity); } + var dbContext = await GetDbContextAsync(GetCancellationToken(cancellationToken)); + var collection = dbContext.Collection(); + if (BulkOperationProvider != null) { - await BulkOperationProvider.DeleteManyAsync(this, entities, SessionHandle, autoSave, cancellationToken); + await BulkOperationProvider.DeleteManyAsync(this, entityArray, dbContext.SessionHandle, autoSave, cancellationToken); return; } - var entitiesCount = entities.Count(); + var entitiesCount = entityArray.Count(); if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity))) { UpdateResult updateResult; - if (SessionHandle != null) + if (dbContext.SessionHandle != null) { - updateResult = await Collection.UpdateManyAsync( - SessionHandle, - CreateEntitiesFilter(entities), + updateResult = await collection.UpdateManyAsync( + dbContext.SessionHandle, + CreateEntitiesFilter(entityArray), Builders.Update.Set(x => ((ISoftDelete)x).IsDeleted, true) ); } else { - updateResult = await Collection.UpdateManyAsync( - CreateEntitiesFilter(entities), + updateResult = await collection.UpdateManyAsync( + CreateEntitiesFilter(entityArray), Builders.Update.Set(x => ((ISoftDelete)x).IsDeleted, true) ); } @@ -325,17 +370,17 @@ namespace Volo.Abp.Domain.Repositories.MongoDB else { DeleteResult deleteResult; - if (SessionHandle != null) + if (dbContext.SessionHandle != null) { - deleteResult = await Collection.DeleteManyAsync( - SessionHandle, - CreateEntitiesFilter(entities) + deleteResult = await collection.DeleteManyAsync( + dbContext.SessionHandle, + CreateEntitiesFilter(entityArray) ); } else { - deleteResult = await Collection.DeleteManyAsync( - CreateEntitiesFilter(entities) + deleteResult = await collection.DeleteManyAsync( + CreateEntitiesFilter(entityArray) ); } @@ -346,38 +391,44 @@ namespace Volo.Abp.Domain.Repositories.MongoDB } } - public async override Task> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default) + public override async Task> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable().ToListAsync(GetCancellationToken(cancellationToken)); + cancellationToken = GetCancellationToken(cancellationToken); + return await (await GetMongoQueryableAsync(cancellationToken)).ToListAsync(cancellationToken); } - public async override Task GetCountAsync(CancellationToken cancellationToken = default) + public override async Task GetCountAsync(CancellationToken cancellationToken = default) { - return await GetMongoQueryable().LongCountAsync(GetCancellationToken(cancellationToken)); + cancellationToken = GetCancellationToken(cancellationToken); + return await (await GetMongoQueryableAsync(cancellationToken)).LongCountAsync(cancellationToken); } - public async override Task> GetPagedListAsync( + public override async Task> GetPagedListAsync( int skipCount, int maxResultCount, string sorting, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + cancellationToken = GetCancellationToken(cancellationToken); + + return await (await GetMongoQueryableAsync(cancellationToken)) .OrderBy(sorting) .As>() .PageBy>(skipCount, maxResultCount) - .ToListAsync(GetCancellationToken(cancellationToken)); + .ToListAsync(cancellationToken); } - public async override Task DeleteAsync( + public override async Task DeleteAsync( Expression> predicate, bool autoSave = false, CancellationToken cancellationToken = default) { - var entities = await GetMongoQueryable() + cancellationToken = GetCancellationToken(cancellationToken); + + var entities = await (await GetMongoQueryableAsync(cancellationToken)) .Where(predicate) - .ToListAsync(GetCancellationToken(cancellationToken)); + .ToListAsync(cancellationToken); foreach (var entity in entities) { @@ -385,25 +436,49 @@ namespace Volo.Abp.Domain.Repositories.MongoDB } } + [Obsolete("Use GetQueryableAsync method.")] protected override IQueryable GetQueryable() { return GetMongoQueryable(); } - public async override Task FindAsync( + public override async Task> GetQueryableAsync() + { + return await GetMongoQueryableAsync(); + } + + public override async Task FindAsync( Expression> predicate, bool includeDetails = true, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(predicate) .SingleOrDefaultAsync(GetCancellationToken(cancellationToken)); } + [Obsolete("Use GetMongoQueryableAsync method.")] public virtual IMongoQueryable GetMongoQueryable() { - return ApplyDataFilters(SessionHandle != null ? Collection.AsQueryable(SessionHandle) : Collection.AsQueryable()); + return ApplyDataFilters( + SessionHandle != null + ? Collection.AsQueryable(SessionHandle) + : Collection.AsQueryable() + ); + } + + public async Task> GetMongoQueryableAsync(CancellationToken cancellationToken = default) + { + var dbContext = await GetDbContextAsync(cancellationToken); + var collection = dbContext.Collection(); + + return ApplyDataFilters( + dbContext.SessionHandle != null + ? collection.AsQueryable(dbContext.SessionHandle) + : collection.AsQueryable() + ); } + protected virtual bool IsHardDeleted(TEntity entity) { var hardDeletedEntities = UnitOfWorkManager?.Current?.Items.GetOrDefault(UnitOfWorkItemNames.HardDeletedEntities) as HashSet; @@ -552,30 +627,19 @@ namespace Volo.Abp.Domain.Repositories.MongoDB throw new AbpDbConcurrencyException("Database operation expected to affect 1 row but actually affected 0 row. Data may have been modified or deleted since entities were loaded. This exception has been thrown on optimistic concurrency check."); } - /// - /// IMongoQueryable - /// - /// + [Obsolete("This method will be removed in future versions.")] public QueryableExecutionModel GetExecutionModel() { return GetMongoQueryable().GetExecutionModel(); } - /// - /// IMongoQueryable - /// - /// - /// + [Obsolete("This method will be removed in future versions.")] public IAsyncCursor ToCursor(CancellationToken cancellationToken = new CancellationToken()) { return GetMongoQueryable().ToCursor(cancellationToken); } - /// - /// IMongoQueryable - /// - /// - /// + [Obsolete("This method will be removed in future versions.")] public Task> ToCursorAsync(CancellationToken cancellationToken = new CancellationToken()) { return GetMongoQueryable().ToCursorAsync(cancellationToken); @@ -616,16 +680,21 @@ namespace Volo.Abp.Domain.Repositories.MongoDB bool includeDetails = true, CancellationToken cancellationToken = default) { - if (SessionHandle != null) + cancellationToken = GetCancellationToken(cancellationToken); + + var dbContext = await GetDbContextAsync(cancellationToken); + var collection = dbContext.Collection(); + + if (dbContext.SessionHandle != null) { - return await Collection - .Find(SessionHandle, RepositoryFilterer.CreateEntityFilter(id, true)) - .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); + return await collection + .Find(dbContext.SessionHandle, RepositoryFilterer.CreateEntityFilter(id, true)) + .FirstOrDefaultAsync(cancellationToken); } - return await Collection + return await collection .Find(RepositoryFilterer.CreateEntityFilter(id, true)) - .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); + .FirstOrDefaultAsync(cancellationToken); } public virtual Task DeleteAsync( @@ -638,9 +707,11 @@ namespace Volo.Abp.Domain.Repositories.MongoDB public virtual async Task DeleteManyAsync([NotNull] IEnumerable ids, bool autoSave = false, CancellationToken cancellationToken = default) { - var entities = await GetMongoQueryable() + cancellationToken = GetCancellationToken(cancellationToken); + + var entities = await (await GetMongoQueryableAsync(cancellationToken)) .Where(x => ids.Contains(x.Id)) - .ToListAsync(GetCancellationToken(cancellationToken)); + .ToListAsync(cancellationToken); await DeleteManyAsync(entities, autoSave, cancellationToken); } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs index 12da0afaa2..ff367dc554 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using MongoDB.Driver; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Entities; @@ -8,24 +9,45 @@ namespace Volo.Abp.Domain.Repositories { public static class MongoDbCoreRepositoryExtensions { + [Obsolete("Use GetDatabaseAsync method.")] public static IMongoDatabase GetDatabase(this IBasicRepository repository) where TEntity : class, IEntity { return repository.ToMongoDbRepository().Database; } + public static Task GetDatabaseAsync(this IBasicRepository repository) + where TEntity : class, IEntity + { + return repository.ToMongoDbRepository().GetDatabaseAsync(); + } + + [Obsolete("Use GetCollection method.")] public static IMongoCollection GetCollection(this IBasicRepository repository) where TEntity : class, IEntity { return repository.ToMongoDbRepository().Collection; } + public static Task> GetCollectionAsync(this IBasicRepository repository) + where TEntity : class, IEntity + { + return repository.ToMongoDbRepository().GetCollectionAsync(); + } + + [Obsolete("Use GetMongoQueryableAsync method.")] public static IMongoQueryable GetMongoQueryable(this IBasicRepository repository) where TEntity : class, IEntity { return repository.ToMongoDbRepository().GetMongoQueryable(); } + public static Task> GetMongoQueryableAsync(this IBasicRepository repository) + where TEntity : class, IEntity + { + return repository.ToMongoDbRepository().GetMongoQueryableAsync(); + } + public static IMongoDbRepository ToMongoDbRepository(this IBasicRepository repository) where TEntity : class, IEntity { @@ -38,4 +60,4 @@ namespace Volo.Abp.Domain.Repositories return mongoDbRepository; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoDbContextProvider.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoDbContextProvider.cs index 9f89054dcc..959cb39df1 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoDbContextProvider.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoDbContextProvider.cs @@ -1,8 +1,15 @@ -namespace Volo.Abp.MongoDB +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Volo.Abp.MongoDB { - public interface IMongoDbContextProvider + public interface IMongoDbContextProvider where TMongoDbContext : IAbpMongoDbContext { + [Obsolete("Use CreateDbContextAsync")] TMongoDbContext GetDbContext(); + + Task GetDbContextAsync(CancellationToken cancellationToken = default); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs index a8dc34e83a..52c5edd1d3 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs @@ -12,7 +12,7 @@ using Volo.Abp.DynamicProxy; namespace Volo.Abp.MongoDB { - public class MongoDbAsyncQueryableProvider : IAsyncQueryableProvider, ITransientDependency + public class MongoDbAsyncQueryableProvider : IAsyncQueryableProvider, ISingletonDependency { public bool CanExecute(IQueryable queryable) { diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs index d3d8a419fb..724e7673fc 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs @@ -1,28 +1,48 @@ using System; +using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using MongoDB.Bson; using MongoDB.Driver; using Volo.Abp.Data; using Volo.Abp.MongoDB; +using Volo.Abp.Threading; namespace Volo.Abp.Uow.MongoDB { public class UnitOfWorkMongoDbContextProvider : IMongoDbContextProvider where TMongoDbContext : IAbpMongoDbContext { + public ILogger> Logger { get; set; } + private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IConnectionStringResolver _connectionStringResolver; + private readonly ICancellationTokenProvider _cancellationTokenProvider; public UnitOfWorkMongoDbContextProvider( IUnitOfWorkManager unitOfWorkManager, - IConnectionStringResolver connectionStringResolver) + IConnectionStringResolver connectionStringResolver, + ICancellationTokenProvider cancellationTokenProvider) { _unitOfWorkManager = unitOfWorkManager; _connectionStringResolver = connectionStringResolver; + _cancellationTokenProvider = cancellationTokenProvider; + + Logger = NullLogger>.Instance; } + [Obsolete("Use CreateDbContextAsync")] public TMongoDbContext GetDbContext() { + Logger.LogWarning( + "UnitOfWorkDbContextProvider.GetDbContext is deprecated. Use GetDbContextAsync instead! " + + "You are probably using LINQ (LINQ extensions) directly on a repository. In this case, use repository.GetQueryableAsync() method " + + "to obtain an IQueryable instance and use LINQ (LINQ extensions) on this object. " + ); + Logger.LogWarning(Environment.StackTrace.Truncate(2048)); + var unitOfWork = _unitOfWorkManager.Current; if (unitOfWork == null) { @@ -48,6 +68,46 @@ namespace Volo.Abp.Uow.MongoDB return ((MongoDbDatabaseApi) databaseApi).DbContext; } + public async Task GetDbContextAsync(CancellationToken cancellationToken = default) + { + var unitOfWork = _unitOfWorkManager.Current; + if (unitOfWork == null) + { + throw new AbpException( + $"A {nameof(IMongoDatabase)} instance can only be created inside a unit of work!"); + } + + var connectionString = await _connectionStringResolver.ResolveAsync(); + var dbContextKey = $"{typeof(TMongoDbContext).FullName}_{connectionString}"; + + var mongoUrl = new MongoUrl(connectionString); + var databaseName = mongoUrl.DatabaseName; + if (databaseName.IsNullOrWhiteSpace()) + { + databaseName = ConnectionStringNameAttribute.GetConnStringName(); + } + + //TODO: Create only single MongoDbClient per connection string in an application (extract MongoClientCache for example). + var databaseApi = unitOfWork.FindDatabaseApi(dbContextKey); + if (databaseApi == null) + { + databaseApi = new MongoDbDatabaseApi( + await CreateDbContextAsync( + unitOfWork, + mongoUrl, + databaseName, + cancellationToken + ) + ); + + unitOfWork.AddDatabaseApi(dbContextKey, databaseApi); + } + + return ((MongoDbDatabaseApi) databaseApi).DbContext; + } + + [Obsolete("Use CreateDbContextAsync")] + private TMongoDbContext CreateDbContext(IUnitOfWork unitOfWork, MongoUrl mongoUrl, string databaseName) { var client = new MongoClient(mongoUrl); @@ -64,7 +124,34 @@ namespace Volo.Abp.Uow.MongoDB return dbContext; } - public TMongoDbContext CreateDbContextWithTransaction( + private async Task CreateDbContextAsync( + IUnitOfWork unitOfWork, + MongoUrl mongoUrl, + string databaseName, + CancellationToken cancellationToken = default) + { + var client = new MongoClient(mongoUrl); + var database = client.GetDatabase(databaseName); + + if (unitOfWork.Options.IsTransactional) + { + return await CreateDbContextWithTransactionAsync( + unitOfWork, + mongoUrl, + client, + database, + cancellationToken + ); + } + + var dbContext = unitOfWork.ServiceProvider.GetRequiredService(); + dbContext.ToAbpMongoDbContext().InitializeDatabase(database, client, null); + + return dbContext; + } + + [Obsolete("Use CreateDbContextWithTransactionAsync")] + private TMongoDbContext CreateDbContextWithTransaction( IUnitOfWork unitOfWork, MongoUrl url, MongoClient client, @@ -99,5 +186,47 @@ namespace Volo.Abp.Uow.MongoDB return dbContext; } + + private async Task CreateDbContextWithTransactionAsync( + IUnitOfWork unitOfWork, + MongoUrl url, + MongoClient client, + IMongoDatabase database, + CancellationToken cancellationToken = default) + { + var transactionApiKey = $"MongoDb_{url}"; + var activeTransaction = unitOfWork.FindTransactionApi(transactionApiKey) as MongoDbTransactionApi; + var dbContext = unitOfWork.ServiceProvider.GetRequiredService(); + + if (activeTransaction?.SessionHandle == null) + { + var session = await client.StartSessionAsync(cancellationToken: GetCancellationToken(cancellationToken)); + + if (unitOfWork.Options.Timeout.HasValue) + { + session.AdvanceOperationTime(new BsonTimestamp(unitOfWork.Options.Timeout.Value)); + } + + session.StartTransaction(); + + unitOfWork.AddTransactionApi( + transactionApiKey, + new MongoDbTransactionApi(session) + ); + + dbContext.ToAbpMongoDbContext().InitializeDatabase(database, client, session); + } + else + { + dbContext.ToAbpMongoDbContext().InitializeDatabase(database, client, activeTransaction.SessionHandle); + } + + return dbContext; + } + + protected virtual CancellationToken GetCancellationToken(CancellationToken preferredValue = default) + { + return _cancellationTokenProvider.FallbackToProvider(preferredValue); + } } } diff --git a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantStore.cs b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantStore.cs index 7125a97405..6c66044e37 100644 --- a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantStore.cs +++ b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantStore.cs @@ -9,8 +9,10 @@ namespace Volo.Abp.MultiTenancy Task FindAsync(Guid id); + [Obsolete("Use FindAsync method.")] TenantConfiguration Find(string name); + [Obsolete("Use FindAsync method.")] TenantConfiguration Find(Guid id); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenantConnectionStringResolver.cs b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenantConnectionStringResolver.cs index d92409fe0d..0d82419013 100644 --- a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenantConnectionStringResolver.cs +++ b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenantConnectionStringResolver.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Volo.Abp.Data; @@ -23,6 +24,58 @@ namespace Volo.Abp.MultiTenancy _serviceProvider = serviceProvider; } + public override async Task ResolveAsync(string connectionStringName = null) + { + //No current tenant, fallback to default logic + if (_currentTenant.Id == null) + { + return await base.ResolveAsync(connectionStringName); + } + + using (var serviceScope = _serviceProvider.CreateScope()) + { + var tenantStore = serviceScope + .ServiceProvider + .GetRequiredService(); + + var tenant = await tenantStore.FindAsync(_currentTenant.Id.Value); + + if (tenant?.ConnectionStrings == null) + { + return await base.ResolveAsync(connectionStringName); + } + + //Requesting default connection string + if (connectionStringName == null) + { + return tenant.ConnectionStrings.Default ?? + Options.ConnectionStrings.Default; + } + + //Requesting specific connection string + var connString = tenant.ConnectionStrings.GetOrDefault(connectionStringName); + if (connString != null) + { + return connString; + } + + /* Requested a specific connection string, but it's not specified for the tenant. + * - If it's specified in options, use it. + * - If not, use tenant's default conn string. + */ + + var connStringInOptions = Options.ConnectionStrings.GetOrDefault(connectionStringName); + if (connStringInOptions != null) + { + return connStringInOptions; + } + + return tenant.ConnectionStrings.Default ?? + Options.ConnectionStrings.Default; + } + } + + [Obsolete("Use ResolveAsync method.")] public override string Resolve(string connectionStringName = null) { //No current tenant, fallback to default logic diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/EntityExtensionConfiguration.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/EntityExtensionConfiguration.cs index 6733688a91..c2b56515b4 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/EntityExtensionConfiguration.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/EntityExtensionConfiguration.cs @@ -67,7 +67,8 @@ namespace Volo.Abp.ObjectExtending.Modularity lookupTextPropertyName, () => new ExtensionPropertyConfiguration(this, typeof(string), lookupTextPropertyName) ); - lookupTextPropertyInfo.DisplayName = propertyInfo.DisplayName ?? new FixedLocalizableString(propertyInfo.Name); + + lookupTextPropertyInfo.DisplayName = propertyInfo.DisplayName; } [NotNull] diff --git a/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs b/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs index 2429f617d9..fc9ba26367 100644 --- a/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs +++ b/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs @@ -16,9 +16,6 @@ namespace Volo.Abp.Quartz { var options = context.Services.ExecutePreConfiguredActions(); - // TODO: Remove this once Pomelo update MySqlConnector to >= 1.0.0 : https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/pull/1103 - AdaptMysqlConnector(); - context.Services.AddQuartz(options.Properties, build => { // these are the defaults @@ -55,7 +52,7 @@ namespace Volo.Abp.Quartz context.Services.AddSingleton(serviceProvider => { - return AsyncHelper.RunSync(() => serviceProvider.GetService().GetScheduler()); + return AsyncHelper.RunSync(() => serviceProvider.GetRequiredService().GetScheduler()); }); Configure(quartzOptions => @@ -69,7 +66,7 @@ namespace Volo.Abp.Quartz { var options = context.ServiceProvider.GetRequiredService>().Value; - _scheduler = context.ServiceProvider.GetService(); + _scheduler = context.ServiceProvider.GetRequiredService(); AsyncHelper.RunSync(() => options.StartSchedulerFactory.Invoke(_scheduler)); } @@ -81,28 +78,5 @@ namespace Volo.Abp.Quartz AsyncHelper.RunSync(() => _scheduler.Shutdown()); } } - - private void AdaptMysqlConnector() - { - var mySqlAvailable = System.Type.GetType("MySql.Data.MySqlClient.MySqlConnection, MySqlConnector") != null; - if (mySqlAvailable) - { - // Overriding the default 'MySqlConnector' provider to use the old 'MySql.Data' namespace found in MySqlConnector < 1.0.0 - DbProvider.RegisterDbMetadata("MySqlConnector", new DbMetadata() - { - ProductName = "MySQL, MySqlConnector provider", - AssemblyName = "MySqlConnector", - ConnectionType = System.Type.GetType("MySql.Data.MySqlClient.MySqlConnection, MySqlConnector"), - CommandType = System.Type.GetType("MySql.Data.MySqlClient.MySqlCommand, MySqlConnector"), - ParameterType = System.Type.GetType("MySql.Data.MySqlClient.MySqlParameter, MySqlConnector"), - ParameterDbType = System.Type.GetType("MySql.Data.MySqlClient.MySqlDbType, MySqlConnector"), - ParameterDbTypePropertyName = "MySqlDbType", - ParameterNamePrefix = "?", - ExceptionType = System.Type.GetType("MySql.Data.MySqlClient.MySqlException, MySqlConnector"), - BindByName = true, - DbBinaryTypeName = "Blob" - }); - } - } } } diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/AsyncQueryableExecuter.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/AsyncQueryableExecuter.cs index f5b3cf3a6d..b7ac83dc5f 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/AsyncQueryableExecuter.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/AsyncQueryableExecuter.cs @@ -8,7 +8,7 @@ using Volo.Abp.DependencyInjection; namespace Volo.Abp.Linq { - public class AsyncQueryableExecuter : IAsyncQueryableExecuter, ITransientDependency + public class AsyncQueryableExecuter : IAsyncQueryableExecuter, ISingletonDependency { protected IEnumerable Providers { get; } diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWorkTransactionBehaviourProvider.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWorkTransactionBehaviourProvider.cs new file mode 100644 index 0000000000..1db7dac938 --- /dev/null +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWorkTransactionBehaviourProvider.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.Uow +{ + public interface IUnitOfWorkTransactionBehaviourProvider + { + bool? IsTransactional { get; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/NullUnitOfWorkTransactionBehaviourProvider.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/NullUnitOfWorkTransactionBehaviourProvider.cs new file mode 100644 index 0000000000..2b302d303a --- /dev/null +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/NullUnitOfWorkTransactionBehaviourProvider.cs @@ -0,0 +1,9 @@ +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Uow +{ + public class NullUnitOfWorkTransactionBehaviourProvider : IUnitOfWorkTransactionBehaviourProvider, ISingletonDependency + { + public bool? IsTransactional => null; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs index b4158229fe..d53acc8f66 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs @@ -11,6 +11,8 @@ namespace Volo.Abp.Uow { public class UnitOfWork : IUnitOfWork, ITransientDependency { + public const string UnitOfWorkReservationName = "_AbpActionUnitOfWork"; + public Guid Id { get; } = Guid.NewGuid(); public IAbpUnitOfWorkOptions Options { get; private set; } @@ -302,7 +304,7 @@ namespace Volo.Abp.Uow } } } - + protected virtual async Task CommitTransactionsAsync() { foreach (var transaction in GetAllActiveTransactionApis()) diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkFailedEventArgs.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkFailedEventArgs.cs index df867c2320..ed225ccc58 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkFailedEventArgs.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkFailedEventArgs.cs @@ -9,8 +9,8 @@ namespace Volo.Abp.Uow public class UnitOfWorkFailedEventArgs : UnitOfWorkEventArgs { /// - /// Exception that caused failure. This is set only if an error occurred during . - /// Can be null if there is no exception, but is not called. + /// Exception that caused failure. This is set only if an error occurred during . + /// Can be null if there is no exception, but is not called. /// Can be null if another exception occurred during the UOW. /// [CanBeNull] diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptor.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptor.cs index f5afcea494..464b6bb871 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptor.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptor.cs @@ -10,15 +10,20 @@ namespace Volo.Abp.Uow public class UnitOfWorkInterceptor : AbpInterceptor, ITransientDependency { private readonly IUnitOfWorkManager _unitOfWorkManager; + private readonly IUnitOfWorkTransactionBehaviourProvider _transactionBehaviourProvider; private readonly AbpUnitOfWorkDefaultOptions _defaultOptions; - public UnitOfWorkInterceptor(IUnitOfWorkManager unitOfWorkManager, IOptions options) + public UnitOfWorkInterceptor( + IUnitOfWorkManager unitOfWorkManager, + IOptions options, + IUnitOfWorkTransactionBehaviourProvider transactionBehaviourProvider) { _unitOfWorkManager = unitOfWorkManager; + _transactionBehaviourProvider = transactionBehaviourProvider; _defaultOptions = options.Value; } - public async override Task InterceptAsync(IAbpMethodInvocation invocation) + public override async Task InterceptAsync(IAbpMethodInvocation invocation) { if (!UnitOfWorkHelper.IsUnitOfWorkMethod(invocation.Method, out var unitOfWorkAttribute)) { @@ -26,7 +31,16 @@ namespace Volo.Abp.Uow return; } - using (var uow = _unitOfWorkManager.Begin(CreateOptions(invocation, unitOfWorkAttribute))) + var options = CreateOptions(invocation, unitOfWorkAttribute); + + //Trying to begin a reserved UOW by AbpUnitOfWorkMiddleware + if (_unitOfWorkManager.TryBeginReserved(UnitOfWork.UnitOfWorkReservationName, options)) + { + await invocation.ProceedAsync(); + return; + } + + using (var uow = _unitOfWorkManager.Begin(options)) { await invocation.ProceedAsync(); await uow.CompleteAsync(); @@ -42,7 +56,8 @@ namespace Volo.Abp.Uow if (unitOfWorkAttribute?.IsTransactional == null) { options.IsTransactional = _defaultOptions.CalculateIsTransactional( - autoValue: !invocation.Method.Name.StartsWith("Get", StringComparison.InvariantCultureIgnoreCase) + autoValue: _transactionBehaviourProvider.IsTransactional + ?? !invocation.Method.Name.StartsWith("Get", StringComparison.InvariantCultureIgnoreCase) ); } diff --git a/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs b/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs index 8c647c92c4..8ca1228ee6 100644 --- a/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs +++ b/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs @@ -54,13 +54,13 @@ namespace Volo.Abp.Auditing public class MyAuditedObject1 : IMyAuditedObject { - public async virtual Task DoItAsync(InputObject inputObject) + public virtual Task DoItAsync(InputObject inputObject) { - return new ResultObject + return Task.FromResult(new ResultObject { Value1 = inputObject.Value1 + "-result", Value2 = inputObject.Value2 + 1 - }; + }); } } diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AbpAutoMapperModule_Basic_Tests.cs b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AbpAutoMapperModule_Basic_Tests.cs index 3ac2246dcc..ea70649350 100644 --- a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AbpAutoMapperModule_Basic_Tests.cs +++ b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AbpAutoMapperModule_Basic_Tests.cs @@ -38,12 +38,12 @@ namespace Volo.Abp.AutoMapper } //[Fact] TODO: Disabled because of https://github.com/AutoMapper/AutoMapper/pull/2379#issuecomment-355899664 - public void Should_Not_Map_Objects_With_AutoMap_Attributes() + /*public void Should_Not_Map_Objects_With_AutoMap_Attributes() { Assert.ThrowsAny(() => { _objectMapper.Map(new MyEntity {Number = 42}); }); - } + }*/ } } diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_Dependency_Injection_Tests.cs b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_Dependency_Injection_Tests.cs new file mode 100644 index 0000000000..56c5e6f061 --- /dev/null +++ b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_Dependency_Injection_Tests.cs @@ -0,0 +1,62 @@ +using AutoMapper; +using Shouldly; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Testing; +using Xunit; +using IObjectMapper = Volo.Abp.ObjectMapping.IObjectMapper; + +namespace Volo.Abp.AutoMapper +{ + public class AutoMapper_Dependency_Injection_Tests : AbpIntegratedTest + { + private readonly IObjectMapper _objectMapper; + + public AutoMapper_Dependency_Injection_Tests() + { + _objectMapper = GetRequiredService(); + } + + [Fact] + public void Should_Registered_AutoMapper_Service() + { + GetService().ShouldNotBeNull(); + } + + [Fact] + public void Custom_MappingAction_Test() + { + var sourceModel = new SourceModel + { + Name = "Source" + }; + + _objectMapper.Map(sourceModel).Name.ShouldBe(nameof(CustomMappingActionService)); + } + + public class SourceModel + { + public string Name { get; set; } + } + + public class DestModel + { + public string Name { get; set; } + } + + public class MapperActionProfile : Profile + { + public MapperActionProfile() + { + CreateMap().AfterMap(); + } + } + + public class CustomMappingActionService : IMappingAction + { + public void Process(SourceModel source, DestModel destination, ResolutionContext context) + { + destination.Name = nameof(CustomMappingActionService); + } + } + } +} diff --git a/framework/test/Volo.Abp.Dapper.Tests/Volo/Abp/Dapper/Repositories/PersonDapperRepository.cs b/framework/test/Volo.Abp.Dapper.Tests/Volo/Abp/Dapper/Repositories/PersonDapperRepository.cs index b5127e3d7e..e4510a366a 100644 --- a/framework/test/Volo.Abp.Dapper.Tests/Volo/Abp/Dapper/Repositories/PersonDapperRepository.cs +++ b/framework/test/Volo.Abp.Dapper.Tests/Volo/Abp/Dapper/Repositories/PersonDapperRepository.cs @@ -17,14 +17,19 @@ namespace Volo.Abp.Dapper.Repositories public virtual async Task> GetAllPersonNames() { - return (await DbConnection.QueryAsync("select Name from People", transaction: DbTransaction)) - .ToList(); + return (await (await GetDbConnectionAsync()) + .QueryAsync( + "select Name from People", + transaction: await GetDbTransactionAsync() + ) + ).ToList(); } public virtual async Task UpdatePersonNames(string name) { - return await DbConnection.ExecuteAsync("update People set Name = @NewName", new { NewName = name }, - DbTransaction); + return await (await GetDbConnectionAsync()) + .ExecuteAsync("update People set Name = @NewName", new {NewName = name}, + await GetDbTransactionAsync()); } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.Data.Tests/Volo/Abp/Data/ConnectionStringResolver_Tests.cs b/framework/test/Volo.Abp.Data.Tests/Volo/Abp/Data/ConnectionStringResolver_Tests.cs index d13c89671e..3971c29ff0 100644 --- a/framework/test/Volo.Abp.Data.Tests/Volo/Abp/Data/ConnectionStringResolver_Tests.cs +++ b/framework/test/Volo.Abp.Data.Tests/Volo/Abp/Data/ConnectionStringResolver_Tests.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.DependencyInjection; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Shouldly; using Volo.Abp.Modularity; using Volo.Abp.Testing; @@ -21,21 +22,21 @@ namespace Volo.Abp.Data } [Fact] - public void Should_Get_Default_ConnString_By_Default() + public async Task Should_Get_Default_ConnString_By_Default() { - _connectionStringResolver.Resolve().ShouldBe(DefaultConnString); + (await _connectionStringResolver.ResolveAsync()).ShouldBe(DefaultConnString); } [Fact] - public void Should_Get_Specific_ConnString_IfDefined() + public async Task Should_Get_Specific_ConnString_IfDefined() { - _connectionStringResolver.Resolve(Database1Name).ShouldBe(Database1ConnString); + (await _connectionStringResolver.ResolveAsync(Database1Name)).ShouldBe(Database1ConnString); } [Fact] - public void Should_Get_Default_ConnString_If_Not_Specified() + public async Task Should_Get_Default_ConnString_If_Not_Specified() { - _connectionStringResolver.Resolve(Database2Name).ShouldBe(DefaultConnString); + (await _connectionStringResolver.ResolveAsync(Database2Name)).ShouldBe(DefaultConnString); } [DependsOn(typeof(AbpDataModule))] diff --git a/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs index baf49f4314..85696fae21 100644 --- a/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs +++ b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs @@ -242,11 +242,17 @@ namespace Volo.Abp.Domain.Repositories where TEntity : class, IEntity { + [Obsolete("Use GetQueryableAsync method.")] protected override IQueryable GetQueryable() { throw new NotImplementedException(); } + public override Task> GetQueryableAsync() + { + throw new NotImplementedException(); + } + public override Task FindAsync(Expression> predicate, bool includeDetails = true, CancellationToken cancellationToken = default) { throw new NotImplementedException(); diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DbContext_Replace_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DbContext_Replace_Tests.cs index 7bc4af2e31..977cb8522a 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DbContext_Replace_Tests.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DbContext_Replace_Tests.cs @@ -26,12 +26,12 @@ namespace Volo.Abp.EntityFrameworkCore { (ServiceProvider.GetRequiredService() is TestAppDbContext).ShouldBeTrue(); - using (_unitOfWorkManager.Begin()) + using (var uow = _unitOfWorkManager.Begin()) { - (_dummyRepository.GetDbContext() is IThirdDbContext).ShouldBeTrue(); - (_dummyRepository.GetDbContext() is TestAppDbContext).ShouldBeTrue(); + ((await _dummyRepository.GetDbContextAsync()) is IThirdDbContext).ShouldBeTrue(); + ((await _dummyRepository.GetDbContextAsync()) is TestAppDbContext).ShouldBeTrue(); - await _unitOfWorkManager.Current.CompleteAsync(); + await uow.CompleteAsync(); } } } diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Domain/ExtraProperties_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Domain/ExtraProperties_Tests.cs index f94f16c390..aa1e0080b5 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Domain/ExtraProperties_Tests.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Domain/ExtraProperties_Tests.cs @@ -44,15 +44,13 @@ namespace Volo.Abp.EntityFrameworkCore.Domain [Fact] public async Task An_Extra_Property_Configured_As_Extension2() { - await WithUnitOfWorkAsync(() => + await WithUnitOfWorkAsync(async () => { - var entityEntry = CityRepository.GetDbContext().Attach(new City(Guid.NewGuid(), "NewYork")); + var entityEntry = (await CityRepository.GetDbContextAsync()).Attach(new City(Guid.NewGuid(), "NewYork")); var indexes = entityEntry.Metadata.GetIndexes().ToList(); indexes.ShouldNotBeEmpty(); indexes.ShouldContain(x => x.IsUnique); - return Task.CompletedTask; }); - } } } diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/CityRepository.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/CityRepository.cs index 027f54a03a..cd85cbcb5a 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/CityRepository.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/CityRepository.cs @@ -11,7 +11,7 @@ namespace Volo.Abp.TestApp.EntityFrameworkCore { public class CityRepository : EfCoreRepository, ICityRepository { - public CityRepository(IDbContextProvider dbContextProvider) + public CityRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) { } @@ -24,7 +24,7 @@ namespace Volo.Abp.TestApp.EntityFrameworkCore public async Task> GetPeopleInTheCityAsync(string cityName) { var city = await FindByNameAsync(cityName); - return await DbContext.People.Where(p => p.CityId == city.Id).ToListAsync(); + return await (await GetDbContextAsync()).People.Where(p => p.CityId == city.Id).ToListAsync(); } } } diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/PersonRepository.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/PersonRepository.cs index ab8c1920a7..6413140bf1 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/PersonRepository.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/PersonRepository.cs @@ -18,7 +18,7 @@ namespace Volo.Abp.TestApp.EntityFrameworkCore public async Task GetViewAsync(string name) { - return await DbContext.PersonView.Where(x => x.Name == name).FirstOrDefaultAsync(); + return await (await GetDbContextAsync()).PersonView.Where(x => x.Name == name).FirstOrDefaultAsync(); } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/TestApp/MemoryDb/CityRepository.cs b/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/TestApp/MemoryDb/CityRepository.cs index b6d43dc875..309339e09d 100644 --- a/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/TestApp/MemoryDb/CityRepository.cs +++ b/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/TestApp/MemoryDb/CityRepository.cs @@ -10,21 +10,21 @@ namespace Volo.Abp.TestApp.MemoryDb { public class CityRepository : MemoryDbRepository, ICityRepository { - public CityRepository(IMemoryDatabaseProvider databaseProvider) + public CityRepository(IMemoryDatabaseProvider databaseProvider) : base(databaseProvider) { } - public Task FindByNameAsync(string name) + public async Task FindByNameAsync(string name) { - return Task.FromResult(Collection.FirstOrDefault(c => c.Name == name)); + return (await GetCollectionAsync()).FirstOrDefault(c => c.Name == name); } public async Task> GetPeopleInTheCityAsync(string cityName) { var city = await FindByNameAsync(cityName); - return Database.Collection().Where(p => p.CityId == city.Id).ToList(); + return (await GetDatabaseAsync()).Collection().Where(p => p.CityId == city.Id).ToList(); } } } diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/MongoDbAsyncQueryableProvider_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/MongoDbAsyncQueryableProvider_Tests.cs index ae9be03d57..5335aa11be 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/MongoDbAsyncQueryableProvider_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/MongoDbAsyncQueryableProvider_Tests.cs @@ -25,10 +25,10 @@ namespace Volo.Abp.MongoDB.Repositories } [Fact] - public void CanExecute() + public async Task CanExecuteAsync() { _mongoDbAsyncQueryableProvider.CanExecute(_personRepository).ShouldBeTrue(); - _mongoDbAsyncQueryableProvider.CanExecute(_personRepository.WithDetails()).ShouldBeTrue(); + _mongoDbAsyncQueryableProvider.CanExecute(await _personRepository.WithDetailsAsync()).ShouldBeTrue(); } [Fact] diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/CityRepository.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/CityRepository.cs index bb31883010..df6eed85cc 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/CityRepository.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/CityRepository.cs @@ -19,13 +19,13 @@ namespace Volo.Abp.TestApp.MongoDB public async Task FindByNameAsync(string name) { - return await (await Collection.FindAsync(c => c.Name == name)).FirstOrDefaultAsync(); + return await (await (await GetCollectionAsync()).FindAsync(c => c.Name == name)).FirstOrDefaultAsync(); } public async Task> GetPeopleInTheCityAsync(string cityName) { var city = await FindByNameAsync(cityName); - return await DbContext.People.AsQueryable().Where(p => p.CityId == city.Id).ToListAsync(); + return await (await GetDbContextAsync()).People.AsQueryable().Where(p => p.CityId == city.Id).ToListAsync(); } } } diff --git a/framework/test/Volo.Abp.MultiTenancy.Tests/Volo/Abp/Data/MultiTenancy/MultiTenantConnectionStringResolver_Tests.cs b/framework/test/Volo.Abp.MultiTenancy.Tests/Volo/Abp/Data/MultiTenancy/MultiTenantConnectionStringResolver_Tests.cs index a6e5fab1c8..f6af2bde72 100644 --- a/framework/test/Volo.Abp.MultiTenancy.Tests/Volo/Abp/Data/MultiTenancy/MultiTenantConnectionStringResolver_Tests.cs +++ b/framework/test/Volo.Abp.MultiTenancy.Tests/Volo/Abp/Data/MultiTenancy/MultiTenantConnectionStringResolver_Tests.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Shouldly; using Volo.Abp.MultiTenancy; @@ -49,28 +50,28 @@ namespace Volo.Abp.Data.MultiTenancy } [Fact] - public void All_Tests() + public async Task All_Tests() { //No tenant in current context - _connectionResolver.Resolve().ShouldBe("default-value"); - _connectionResolver.Resolve("db1").ShouldBe("db1-default-value"); + (await _connectionResolver.ResolveAsync()).ShouldBe("default-value"); + (await _connectionResolver.ResolveAsync("db1")).ShouldBe("db1-default-value"); - //Overrided connection strings for tenant1 + //Overriden connection strings for tenant1 using (_currentTenant.Change(_tenant1Id)) { - _connectionResolver.Resolve().ShouldBe("tenant1-default-value"); - _connectionResolver.Resolve("db1").ShouldBe("tenant1-db1-value"); + (await _connectionResolver.ResolveAsync()).ShouldBe("tenant1-default-value"); + (await _connectionResolver.ResolveAsync("db1")).ShouldBe("tenant1-db1-value"); } //No tenant in current context - _connectionResolver.Resolve().ShouldBe("default-value"); - _connectionResolver.Resolve("db1").ShouldBe("db1-default-value"); + (await _connectionResolver.ResolveAsync()).ShouldBe("default-value"); + (await _connectionResolver.ResolveAsync("db1")).ShouldBe("db1-default-value"); //Undefined connection strings for tenant2 using (_currentTenant.Change(_tenant2Id)) { - _connectionResolver.Resolve().ShouldBe("default-value"); - _connectionResolver.Resolve("db1").ShouldBe("db1-default-value"); + (await _connectionResolver.ResolveAsync()).ShouldBe("default-value"); + (await _connectionResolver.ResolveAsync("db1")).ShouldBe("db1-default-value"); } } } diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Queryable_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Queryable_Tests.cs index 6078236380..3ca511a7ea 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Queryable_Tests.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Queryable_Tests.cs @@ -44,24 +44,22 @@ namespace Volo.Abp.TestApp.Testing [Fact] public async Task WithDetails() { - await WithUnitOfWorkAsync(() => + await WithUnitOfWorkAsync(async () => { - var person = PersonRepository.WithDetails().Single(p => p.Id == TestDataBuilder.UserDouglasId); + var person = (await PersonRepository.WithDetailsAsync()).Single(p => p.Id == TestDataBuilder.UserDouglasId); person.Name.ShouldBe("Douglas"); person.Phones.Count.ShouldBe(2); - return Task.CompletedTask; }); } [Fact] public async Task WithDetails_Explicit() { - await WithUnitOfWorkAsync(() => + await WithUnitOfWorkAsync(async () => { - var person = PersonRepository.WithDetails(p => p.Phones).Single(p => p.Id == TestDataBuilder.UserDouglasId); + var person = (await PersonRepository.WithDetailsAsync(p => p.Phones)).Single(p => p.Id == TestDataBuilder.UserDouglasId); person.Name.ShouldBe("Douglas"); person.Phones.Count.ShouldBe(2); - return Task.CompletedTask; }); } } diff --git a/framework/test/Volo.Abp.Uow.Tests/Volo/Abp/Uow/UnitOfWork_Events_Tests.cs b/framework/test/Volo.Abp.Uow.Tests/Volo/Abp/Uow/UnitOfWork_Events_Tests.cs index bf120d2e33..8fd3d68b18 100644 --- a/framework/test/Volo.Abp.Uow.Tests/Volo/Abp/Uow/UnitOfWork_Events_Tests.cs +++ b/framework/test/Volo.Abp.Uow.Tests/Volo/Abp/Uow/UnitOfWork_Events_Tests.cs @@ -26,7 +26,7 @@ namespace Volo.Abp.Uow { uow.OnCompleted(() => { - completed = true; + completed = true; return Task.CompletedTask; }); @@ -50,7 +50,12 @@ namespace Volo.Abp.Uow { using (var childUow = _unitOfWorkManager.Begin()) { - childUow.OnCompleted(async () => completed = true); + childUow.OnCompleted(() => + { + completed = true; + return Task.CompletedTask; + }); + uow.Disposed += (sender, args) => disposed = true; await childUow.CompleteAsync(); @@ -80,9 +85,14 @@ namespace Volo.Abp.Uow using (var uow = _unitOfWorkManager.Begin()) { - uow.OnCompleted(async () => completed = true); - uow.Failed += (sender, args) => failed = true; - uow.Disposed += (sender, args) => disposed = true; + uow.OnCompleted(() => + { + completed = true; + return Task.CompletedTask; + }); + + uow.Failed += (_, _) => failed = true; + uow.Disposed += (_, _) => disposed = true; } completed.ShouldBeFalse(); @@ -101,7 +111,12 @@ namespace Volo.Abp.Uow { using (var uow = _unitOfWorkManager.Begin()) { - uow.OnCompleted(async () => completed = true); + uow.OnCompleted(() => + { + completed = true; + return Task.CompletedTask; + }); + uow.Failed += (sender, args) => failed = true; uow.Disposed += (sender, args) => disposed = true; @@ -125,7 +140,12 @@ namespace Volo.Abp.Uow using (var uow = _unitOfWorkManager.Begin()) { - uow.OnCompleted(async () => completed = true); + uow.OnCompleted(() => + { + completed = true; + return Task.CompletedTask; + }); + uow.Failed += (sender, args) => { failed = true; args.IsRolledback.ShouldBeTrue(); }; uow.Disposed += (sender, args) => disposed = true; diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs index 6677f2d4a2..edb1f3f599 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs @@ -39,7 +39,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore bool includeDetails = false, CancellationToken cancellationToken = default) { - var query = GetListQuery( + var query = await GetListQueryAsync( startTime, endTime, httpMethod, @@ -75,7 +75,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore HttpStatusCode? httpStatusCode = null, CancellationToken cancellationToken = default) { - var query = GetListQuery( + var query = await GetListQueryAsync( startTime, endTime, httpMethod, @@ -94,7 +94,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore return totalCount; } - protected virtual IQueryable GetListQuery( + protected virtual async Task> GetListQueryAsync( DateTime? startTime = null, DateTime? endTime = null, string httpMethod = null, @@ -109,7 +109,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore bool includeDetails = false) { var nHttpStatusCode = (int?) httpStatusCode; - return DbSet.AsNoTracking() + return (await GetDbSetAsync()).AsNoTracking() .IncludeDetails(includeDetails) .WhereIf(startTime.HasValue, auditLog => auditLog.ExecutionTime >= startTime) .WhereIf(endTime.HasValue, auditLog => auditLog.ExecutionTime <= endTime) @@ -127,7 +127,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore public virtual async Task> GetAverageExecutionDurationPerDayAsync(DateTime startDate, DateTime endDate) { - var result = await DbSet.AsNoTracking() + var result = await (await GetDbSetAsync()).AsNoTracking() .Where(a => a.ExecutionTime < endDate.AddDays(1) && a.ExecutionTime > startDate) .OrderBy(t => t.ExecutionTime) .GroupBy(t => new { t.ExecutionTime.Date }) @@ -137,14 +137,20 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore return result.ToDictionary(element => element.Day.ClearTime(), element => element.avgExecutionTime); } + [Obsolete("Use WithDetailsAsync method.")] public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); } + public override async Task> WithDetailsAsync() + { + return (await GetQueryableAsync()).IncludeDetails(); + } + public virtual async Task GetEntityChange(Guid entityChangeId) { - var entityChange = await DbContext.Set() + var entityChange = await (await GetDbContextAsync()).Set() .AsNoTracking() .IncludeDetails() .Where(x => x.Id == entityChangeId) @@ -172,7 +178,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore bool includeDetails = false, CancellationToken cancellationToken = default) { - var query = GetEntityChangeListQuery(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName, includeDetails); + var query = await GetEntityChangeListQueryAsync(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName, includeDetails); return await query.OrderBy(sorting ?? "changeTime desc") .PageBy(skipCount, maxResultCount) @@ -188,7 +194,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore string entityTypeFullName = null, CancellationToken cancellationToken = default) { - var query = GetEntityChangeListQuery(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName); + var query = await GetEntityChangeListQueryAsync(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName); var totalCount = await query.LongCountAsync(GetCancellationToken(cancellationToken)); @@ -197,7 +203,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore public virtual async Task GetEntityChangeWithUsernameAsync(Guid entityChangeId) { - var auditLog = await DbSet.AsNoTracking().IncludeDetails() + var auditLog = await (await GetDbSetAsync()).AsNoTracking().IncludeDetails() .Where(x => x.EntityChanges.Any(y => y.Id == entityChangeId)).FirstAsync(); return new EntityChangeWithUsername() @@ -209,18 +215,20 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore public virtual async Task> GetEntityChangesWithUsernameAsync(string entityId, string entityTypeFullName) { - var query = DbContext.Set() + var dbContext = await GetDbContextAsync(); + + var query = dbContext.Set() .AsNoTracking() .IncludeDetails() .Where(x => x.EntityId == entityId && x.EntityTypeFullName == entityTypeFullName); return await (from e in query - join auditLog in DbSet on e.AuditLogId equals auditLog.Id - select new EntityChangeWithUsername() {EntityChange = e, UserName = auditLog.UserName}) + join auditLog in dbContext.AuditLogs on e.AuditLogId equals auditLog.Id + select new EntityChangeWithUsername {EntityChange = e, UserName = auditLog.UserName}) .OrderByDescending(x => x.EntityChange.ChangeTime).ToListAsync(); } - protected virtual IQueryable GetEntityChangeListQuery( + protected virtual async Task> GetEntityChangeListQueryAsync( Guid? auditLogId = null, DateTime? startTime = null, DateTime? endTime = null, @@ -229,14 +237,16 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore string entityTypeFullName = null, bool includeDetails = false) { - return DbContext.Set().AsNoTracking().IncludeDetails(includeDetails) - .WhereIf(auditLogId.HasValue, e => e.AuditLogId == auditLogId) - .WhereIf(startTime.HasValue, e => e.ChangeTime >= startTime) - .WhereIf(endTime.HasValue, e => e.ChangeTime <= endTime) - .WhereIf(changeType.HasValue, e => e.ChangeType == changeType) - .WhereIf(!string.IsNullOrWhiteSpace(entityId), e => e.EntityId == entityId) - .WhereIf(!string.IsNullOrWhiteSpace(entityTypeFullName), - e => e.EntityTypeFullName.Contains(entityTypeFullName)); + return (await GetDbContextAsync()) + .Set() + .AsNoTracking() + .IncludeDetails(includeDetails) + .WhereIf(auditLogId.HasValue, e => e.AuditLogId == auditLogId) + .WhereIf(startTime.HasValue, e => e.ChangeTime >= startTime) + .WhereIf(endTime.HasValue, e => e.ChangeTime <= endTime) + .WhereIf(changeType.HasValue, e => e.ChangeType == changeType) + .WhereIf(!string.IsNullOrWhiteSpace(entityId), e => e.EntityId == entityId) + .WhereIf(!string.IsNullOrWhiteSpace(entityTypeFullName), e => e.EntityTypeFullName.Contains(entityTypeFullName)); } } } diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs index 14e4dd39c7..95981d6355 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs @@ -40,7 +40,7 @@ namespace Volo.Abp.AuditLogging.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - var query = GetListQuery( + var query = await GetListQueryAsync( startTime, endTime, httpMethod, @@ -74,7 +74,7 @@ namespace Volo.Abp.AuditLogging.MongoDB HttpStatusCode? httpStatusCode = null, CancellationToken cancellationToken = default) { - var query = GetListQuery( + var query = await GetListQueryAsync( startTime, endTime, httpMethod, @@ -94,7 +94,7 @@ namespace Volo.Abp.AuditLogging.MongoDB return count; } - protected virtual IQueryable GetListQuery( + protected virtual async Task> GetListQueryAsync( DateTime? startTime = null, DateTime? endTime = null, string httpMethod = null, @@ -108,7 +108,7 @@ namespace Volo.Abp.AuditLogging.MongoDB HttpStatusCode? httpStatusCode = null, bool includeDetails = false) { - return GetMongoQueryable() + return (await GetMongoQueryableAsync()) .WhereIf(startTime.HasValue, auditLog => auditLog.ExecutionTime >= startTime) .WhereIf(endTime.HasValue, auditLog => auditLog.ExecutionTime <= endTime) .WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null && auditLog.Exceptions != "") @@ -126,7 +126,7 @@ namespace Volo.Abp.AuditLogging.MongoDB public virtual async Task> GetAverageExecutionDurationPerDayAsync(DateTime startDate, DateTime endDate) { - var result = await GetMongoQueryable() + var result = await (await GetMongoQueryableAsync()) .Where(a => a.ExecutionTime < endDate.AddDays(1) && a.ExecutionTime > startDate) .OrderBy(t => t.ExecutionTime) .GroupBy(t => new @@ -143,12 +143,11 @@ namespace Volo.Abp.AuditLogging.MongoDB public virtual async Task GetEntityChange(Guid entityChangeId) { - var entityChange = (await GetMongoQueryable() + var entityChange = (await (await GetMongoQueryableAsync()) .Where(x => x.EntityChanges.Any(y => y.Id == entityChangeId)) .OrderBy(x => x.Id) .FirstAsync()).EntityChanges.FirstOrDefault(x => x.Id == entityChangeId); - if (entityChange == null) { throw new EntityNotFoundException(typeof(EntityChange)); @@ -170,7 +169,7 @@ namespace Volo.Abp.AuditLogging.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - var query = GetEntityChangeListQuery(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName); + var query = await GetEntityChangeListQueryAsync(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName); var auditLogs = await query.As>() .PageBy>(skipCount, maxResultCount) @@ -188,7 +187,7 @@ namespace Volo.Abp.AuditLogging.MongoDB string entityTypeFullName = null, CancellationToken cancellationToken = default) { - var query = GetEntityChangeListQuery(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName); + var query = await GetEntityChangeListQueryAsync(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName); var count = await query.As>().LongCountAsync(GetCancellationToken(cancellationToken)); @@ -197,7 +196,7 @@ namespace Volo.Abp.AuditLogging.MongoDB public virtual async Task GetEntityChangeWithUsernameAsync(Guid entityChangeId) { - var auditLog = (await GetMongoQueryable() + var auditLog = (await (await GetMongoQueryableAsync()) .Where(x => x.EntityChanges.Any(y => y.Id == entityChangeId)) .FirstAsync()); @@ -210,7 +209,7 @@ namespace Volo.Abp.AuditLogging.MongoDB public virtual async Task> GetEntityChangesWithUsernameAsync(string entityId, string entityTypeFullName) { - var auditLogs = await GetMongoQueryable() + var auditLogs = await (await GetMongoQueryableAsync()) .Where(x => x.EntityChanges.Any(y => y.EntityId == entityId && y.EntityTypeFullName == entityTypeFullName)) .As>() .OrderByDescending(x => x.ExecutionTime) @@ -224,7 +223,7 @@ namespace Volo.Abp.AuditLogging.MongoDB {EntityChange = x, UserName = auditLogs.First(y => y.Id == x.AuditLogId).UserName}).ToList(); } - protected virtual IQueryable GetEntityChangeListQuery( + protected virtual async Task> GetEntityChangeListQueryAsync( Guid? auditLogId = null, DateTime? startTime = null, DateTime? endTime = null, @@ -232,7 +231,7 @@ namespace Volo.Abp.AuditLogging.MongoDB string entityId = null, string entityTypeFullName = null) { - return GetMongoQueryable() + return (await GetMongoQueryableAsync()) .SelectMany(x => x.EntityChanges) .WhereIf(auditLogId.HasValue, e => e.Id == auditLogId) .WhereIf(startTime.HasValue, e => e.ChangeTime >= startTime) diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/appsettings.json b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/appsettings.json index e1e6966497..3a8ae55ee8 100644 --- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/appsettings.json +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/appsettings.json @@ -1,5 +1,5 @@ { "ConnectionStrings": { - "Default": "Server=localhost;Database=BackgroundJobsDemoApp;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=localhost;Database=BackgroundJobsDemoApp;Trusted_Connection=True" } } \ No newline at end of file diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/appsettings.json b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/appsettings.json index e1e6966497..3a8ae55ee8 100644 --- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/appsettings.json +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/appsettings.json @@ -1,5 +1,5 @@ { "ConnectionStrings": { - "Default": "Server=localhost;Database=BackgroundJobsDemoApp;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=localhost;Database=BackgroundJobsDemoApp;Trusted_Connection=True" } } \ No newline at end of file diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/EfCoreBackgroundJobRepository.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/EfCoreBackgroundJobRepository.cs index 29d2bb0170..1971faf380 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/EfCoreBackgroundJobRepository.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/EfCoreBackgroundJobRepository.cs @@ -15,7 +15,7 @@ namespace Volo.Abp.BackgroundJobs.EntityFrameworkCore public EfCoreBackgroundJobRepository( IDbContextProvider dbContextProvider, - IClock clock) + IClock clock) : base(dbContextProvider) { Clock = clock; @@ -23,14 +23,13 @@ namespace Volo.Abp.BackgroundJobs.EntityFrameworkCore public virtual async Task> GetWaitingListAsync(int maxResultCount) { - return await GetWaitingListQuery(maxResultCount) - .ToListAsync(); + return await (await GetWaitingListQueryAsync(maxResultCount)).ToListAsync(); } - protected virtual IQueryable GetWaitingListQuery(int maxResultCount) + protected virtual async Task> GetWaitingListQueryAsync(int maxResultCount) { var now = Clock.Now; - return DbSet + return (await GetDbSetAsync()) .Where(t => !t.IsAbandoned && t.NextTryTime <= now) .OrderByDescending(t => t.Priority) .ThenBy(t => t.TryCount) diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs index 4399e15a98..258c9310e2 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs @@ -14,8 +14,8 @@ namespace Volo.Abp.BackgroundJobs.MongoDB protected IClock Clock { get; } public MongoBackgroundJobRepository( - IMongoDbContextProvider dbContextProvider, - IClock clock) + IMongoDbContextProvider dbContextProvider, + IClock clock) : base(dbContextProvider) { Clock = clock; @@ -23,14 +23,13 @@ namespace Volo.Abp.BackgroundJobs.MongoDB public virtual async Task> GetWaitingListAsync(int maxResultCount) { - return await GetWaitingListQuery(maxResultCount) - .ToListAsync(); + return await (await GetWaitingListQuery(maxResultCount)).ToListAsync(); } - protected virtual IMongoQueryable GetWaitingListQuery(int maxResultCount) + protected virtual async Task> GetWaitingListQuery(int maxResultCount) { var now = Clock.Now; - return GetMongoQueryable() + return (await GetMongoQueryableAsync()) .Where(t => !t.IsAbandoned && t.NextTryTime <= now) .OrderByDescending(t => t.Priority) .ThenBy(t => t.TryCount) diff --git a/modules/blob-storing-database/host/BlobStoring.Database.Host.ConsoleApp/src/BlobStoring.Database.Host.ConsoleApp.ConsoleApp/ConsoleAppConsoleAppModule.cs b/modules/blob-storing-database/host/BlobStoring.Database.Host.ConsoleApp/src/BlobStoring.Database.Host.ConsoleApp.ConsoleApp/ConsoleAppConsoleAppModule.cs index 5a6691c439..21f2ed53b8 100644 --- a/modules/blob-storing-database/host/BlobStoring.Database.Host.ConsoleApp/src/BlobStoring.Database.Host.ConsoleApp.ConsoleApp/ConsoleAppConsoleAppModule.cs +++ b/modules/blob-storing-database/host/BlobStoring.Database.Host.ConsoleApp/src/BlobStoring.Database.Host.ConsoleApp.ConsoleApp/ConsoleAppConsoleAppModule.cs @@ -39,7 +39,7 @@ namespace BlobStoring.Database.Host.ConsoleApp.ConsoleApp { Configure(options => { - options.ConnectionStrings.Default = "Server=localhost;Database=BlobStoring_Host;Trusted_Connection=True;MultipleActiveResultSets=true"; + options.ConnectionStrings.Default = "Server=localhost;Database=BlobStoring_Host;Trusted_Connection=True"; }); context.Services.AddAbpDbContext(options => diff --git a/modules/blob-storing-database/host/BlobStoring.Database.Host.ConsoleApp/src/BlobStoring.Database.Host.ConsoleApp.ConsoleApp/appsettings.json b/modules/blob-storing-database/host/BlobStoring.Database.Host.ConsoleApp/src/BlobStoring.Database.Host.ConsoleApp.ConsoleApp/appsettings.json index 2e1ff4f771..13d94f70db 100644 --- a/modules/blob-storing-database/host/BlobStoring.Database.Host.ConsoleApp/src/BlobStoring.Database.Host.ConsoleApp.ConsoleApp/appsettings.json +++ b/modules/blob-storing-database/host/BlobStoring.Database.Host.ConsoleApp/src/BlobStoring.Database.Host.ConsoleApp.ConsoleApp/appsettings.json @@ -1,5 +1,5 @@ { "ConnectionStrings": { - "Default": "Server=localhost;Database=BlobStoring_Host;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=localhost;Database=BlobStoring_Host;Trusted_Connection=True" } } diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobContainerRepository.cs b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobContainerRepository.cs index e1d0764807..64b7e3e40a 100644 --- a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobContainerRepository.cs +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobContainerRepository.cs @@ -10,14 +10,15 @@ namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore { public class EfCoreDatabaseBlobContainerRepository : EfCoreRepository, IDatabaseBlobContainerRepository { - public EfCoreDatabaseBlobContainerRepository(IDbContextProvider dbContextProvider) + public EfCoreDatabaseBlobContainerRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) { } public virtual async Task FindAsync(string name, CancellationToken cancellationToken = default) { - return await DbSet.FirstOrDefaultAsync(x => x.Name == name, GetCancellationToken(cancellationToken)); + return await (await GetDbSetAsync()) + .FirstOrDefaultAsync(x => x.Name == name, GetCancellationToken(cancellationToken)); } } -} \ No newline at end of file +} diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobRepository.cs b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobRepository.cs index 098f6095e4..2ae9331def 100644 --- a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobRepository.cs +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobRepository.cs @@ -20,7 +20,8 @@ namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore string name, CancellationToken cancellationToken = default) { - return await DbSet.FirstOrDefaultAsync( + return await (await GetDbSetAsync()) + .FirstOrDefaultAsync( x => x.ContainerId == containerId && x.Name == name, GetCancellationToken(cancellationToken) ); @@ -31,9 +32,11 @@ namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore string name, CancellationToken cancellationToken = default) { - return await DbSet.AnyAsync( - x => x.ContainerId == containerId && x.Name == name, - GetCancellationToken(cancellationToken)); + return await (await GetDbSetAsync()) + .AnyAsync( + x => x.ContainerId == containerId && x.Name == name, + GetCancellationToken(cancellationToken) + ); } public virtual async Task DeleteAsync( @@ -54,4 +57,4 @@ namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore return true; } } -} \ No newline at end of file +} diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs index 6c5b034fc1..17945a87db 100644 --- a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs @@ -15,35 +15,41 @@ namespace Volo.Abp.BlobStoring.Database.MongoDB public virtual async Task FindAsync(Guid containerId, string name, CancellationToken cancellationToken = default) { - return await GetMongoQueryable().FirstOrDefaultAsync( - x => x.ContainerId == containerId && - x.Name == name, - GetCancellationToken(cancellationToken)); + cancellationToken = GetCancellationToken(cancellationToken); + + return await (await GetMongoQueryableAsync(cancellationToken)) + .FirstOrDefaultAsync( + x => x.ContainerId == containerId && x.Name == name, + cancellationToken + ); } public virtual async Task ExistsAsync(Guid containerId, string name, CancellationToken cancellationToken = default) { - return await GetMongoQueryable().AnyAsync( - x => x.ContainerId == containerId && - x.Name == name, - GetCancellationToken(cancellationToken)); + cancellationToken = GetCancellationToken(cancellationToken); + + return await (await GetMongoQueryableAsync(cancellationToken)) + .AnyAsync( + x => x.ContainerId == containerId && x.Name == name, + cancellationToken + ); } public virtual async Task DeleteAsync( - Guid containerId, + Guid containerId, string name, bool autoSave = false, CancellationToken cancellationToken = default) { var blob = await FindAsync(containerId, name, cancellationToken); - if (blob == null) { return false; } - await base.DeleteAsync(blob, autoSave, cancellationToken: GetCancellationToken(cancellationToken)); + await base.DeleteAsync(blob, autoSave, cancellationToken); + return true; } } -} \ No newline at end of file +} diff --git a/modules/blogging/app/Volo.BloggingTestApp/appsettings.json b/modules/blogging/app/Volo.BloggingTestApp/appsettings.json index c85ffe9489..6d3d120f4e 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/appsettings.json +++ b/modules/blogging/app/Volo.BloggingTestApp/appsettings.json @@ -1,6 +1,6 @@ { "ConnectionStrings": { - "SqlServer": "Server=localhost;Database=BloggingTestApp;Trusted_Connection=True;MultipleActiveResultSets=true", + "SqlServer": "Server=localhost;Database=BloggingTestApp;Trusted_Connection=True", "MongoDb": "mongodb://localhost:27017/BloggingTestApp" } } \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Blogs/EfCoreBlogRepository.cs b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Blogs/EfCoreBlogRepository.cs index 604f7ca8b5..564d45dc7a 100644 --- a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Blogs/EfCoreBlogRepository.cs +++ b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Blogs/EfCoreBlogRepository.cs @@ -17,7 +17,7 @@ namespace Volo.Blogging.Blogs public async Task FindByShortNameAsync(string shortName) { - return await DbSet.FirstOrDefaultAsync(p => p.ShortName == shortName); + return await (await GetDbSetAsync()).FirstOrDefaultAsync(p => p.ShortName == shortName); } } } diff --git a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Comments/EfCoreCommentRepository.cs b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Comments/EfCoreCommentRepository.cs index 751d106071..6c28b521aa 100644 --- a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Comments/EfCoreCommentRepository.cs +++ b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Comments/EfCoreCommentRepository.cs @@ -11,14 +11,14 @@ namespace Volo.Blogging.Comments { public class EfCoreCommentRepository : EfCoreRepository, ICommentRepository { - public EfCoreCommentRepository(IDbContextProvider dbContextProvider) + public EfCoreCommentRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) { } public async Task> GetListOfPostAsync(Guid postId) { - return await DbSet + return await (await GetDbSetAsync()) .Where(a => a.PostId == postId) .OrderBy(a => a.CreationTime) .ToListAsync(); @@ -26,20 +26,20 @@ namespace Volo.Blogging.Comments public async Task GetCommentCountOfPostAsync(Guid postId) { - return await DbSet + return await (await GetDbSetAsync()) .CountAsync(a => a.PostId == postId); } public async Task> GetRepliesOfComment(Guid id) { - return await DbSet + return await (await GetDbSetAsync()) .Where(a => a.RepliedCommentId == id).ToListAsync(); } public async Task DeleteOfPost(Guid id) { - var recordsToDelete = DbSet.Where(pt => pt.PostId == id); - DbSet.RemoveRange(recordsToDelete); + var recordsToDelete = (await GetDbSetAsync()).Where(pt => pt.PostId == id); + (await GetDbSetAsync()).RemoveRange(recordsToDelete); } } } diff --git a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostRepository.cs b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostRepository.cs index b152f3ae7d..a5a84fd340 100644 --- a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostRepository.cs +++ b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostRepository.cs @@ -20,24 +20,24 @@ namespace Volo.Blogging.Posts public async Task> GetPostsByBlogId(Guid id) { - return await DbSet.Where(p => p.BlogId == id).OrderByDescending(p=>p.CreationTime).ToListAsync(); + return await (await GetDbSetAsync()).Where(p => p.BlogId == id).OrderByDescending(p=>p.CreationTime).ToListAsync(); } - public Task IsPostUrlInUseAsync(Guid blogId, string url, Guid? excludingPostId = null) + public async Task IsPostUrlInUseAsync(Guid blogId, string url, Guid? excludingPostId = null) { - var query = DbSet.Where(p => blogId == p.BlogId && p.Url == url); + var query = (await GetDbSetAsync()).Where(p => blogId == p.BlogId && p.Url == url); if (excludingPostId != null) { query = query.Where(p => excludingPostId != p.Id); } - return query.AnyAsync(); + return await query.AnyAsync(); } public async Task GetPostByUrl(Guid blogId, string url) { - var post = await DbSet.FirstOrDefaultAsync(p => p.BlogId == blogId && p.Url == url); + var post = await (await GetDbSetAsync()).FirstOrDefaultAsync(p => p.BlogId == blogId && p.Url == url); if (post == null) { @@ -51,18 +51,18 @@ namespace Volo.Blogging.Posts { if (!descending) { - return await DbSet.Where(x=>x.BlogId==blogId).OrderByDescending(x => x.CreationTime).ToListAsync(); + return await (await GetDbSetAsync()).Where(x=>x.BlogId==blogId).OrderByDescending(x => x.CreationTime).ToListAsync(); } else { - return await DbSet.Where(x => x.BlogId == blogId).OrderBy(x => x.CreationTime).ToListAsync(); + return await (await GetDbSetAsync()).Where(x => x.BlogId == blogId).OrderBy(x => x.CreationTime).ToListAsync(); } } - public override IQueryable WithDetails() + public override async Task> WithDetailsAsync() { - return GetQueryable().IncludeDetails(); + return (await GetQueryableAsync()).IncludeDetails(); } } } diff --git a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Tagging/EfCoreTagRepository.cs b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Tagging/EfCoreTagRepository.cs index 3e897fa7e3..a92ae780da 100644 --- a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Tagging/EfCoreTagRepository.cs +++ b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Tagging/EfCoreTagRepository.cs @@ -19,27 +19,27 @@ namespace Volo.Blogging.Tagging public async Task> GetListAsync(Guid blogId) { - return await DbSet.Where(t=>t.BlogId == blogId).ToListAsync(); + return await (await GetDbSetAsync()).Where(t=>t.BlogId == blogId).ToListAsync(); } public async Task GetByNameAsync(Guid blogId, string name) { - return await DbSet.FirstAsync(t=> t.BlogId == blogId && t.Name == name); + return await (await GetDbSetAsync()).FirstAsync(t=> t.BlogId == blogId && t.Name == name); } public async Task FindByNameAsync(Guid blogId, string name) { - return await DbSet.FirstOrDefaultAsync(t => t.BlogId == blogId && t.Name == name); + return await (await GetDbSetAsync()).FirstOrDefaultAsync(t => t.BlogId == blogId && t.Name == name); } public async Task> GetListAsync(IEnumerable ids) { - return await DbSet.Where(t => ids.Contains(t.Id)).ToListAsync(); + return await (await GetDbSetAsync()).Where(t => ids.Contains(t.Id)).ToListAsync(); } public async Task DecreaseUsageCountOfTagsAsync(List ids, CancellationToken cancellationToken = default) { - var tags = await DbSet + var tags = await (await GetDbSetAsync()) .Where(t => ids.Any(id => id == t.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs index b1c7b5d319..6025dfe3ca 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs @@ -15,7 +15,7 @@ namespace Volo.Blogging.Blogs public async Task FindByShortNameAsync(string shortName) { - return await GetMongoQueryable().FirstOrDefaultAsync(p => p.ShortName == shortName); + return await (await GetMongoQueryableAsync()).FirstOrDefaultAsync(p => p.ShortName == shortName); } } } diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Comments/MongoCommentRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Comments/MongoCommentRepository.cs index b17c7f906f..bbbe60345b 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Comments/MongoCommentRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Comments/MongoCommentRepository.cs @@ -17,7 +17,7 @@ namespace Volo.Blogging.Comments public async Task> GetListOfPostAsync(Guid postId) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync()) .Where(a => a.PostId == postId) .OrderBy(a => a.CreationTime) .ToListAsync(); @@ -25,19 +25,19 @@ namespace Volo.Blogging.Comments public async Task GetCommentCountOfPostAsync(Guid postId) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync()) .CountAsync(a => a.PostId == postId); } public async Task> GetRepliesOfComment(Guid id) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync()) .Where(a => a.RepliedCommentId == id).ToListAsync(); } public async Task DeleteOfPost(Guid id) { - var recordsToDelete = GetMongoQueryable().Where(pt => pt.PostId == id); + var recordsToDelete = (await GetMongoQueryableAsync()).Where(pt => pt.PostId == id); foreach (var record in recordsToDelete) { diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs index e12e5f29de..27f4ad4348 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs @@ -18,25 +18,25 @@ namespace Volo.Blogging.Posts public async Task> GetPostsByBlogId(Guid id) { - return await GetMongoQueryable().Where(p => p.BlogId == id).OrderByDescending(p => p.CreationTime).ToListAsync(); + return await (await GetMongoQueryableAsync()).Where(p => p.BlogId == id).OrderByDescending(p => p.CreationTime).ToListAsync(); } - public Task IsPostUrlInUseAsync(Guid blogId, string url, Guid? excludingPostId = null) + public async Task IsPostUrlInUseAsync(Guid blogId, string url, Guid? excludingPostId = null) { - var query = GetMongoQueryable().Where(p => blogId == p.BlogId && p.Url == url); + var query = (await GetMongoQueryableAsync()).Where(p => blogId == p.BlogId && p.Url == url); if (excludingPostId != null) { query = query.Where(p => excludingPostId != p.Id); } - return query.AnyAsync(); + return await query.AnyAsync(); } public async Task GetPostByUrl(Guid blogId, string url) { - var post = await GetMongoQueryable().FirstOrDefaultAsync(p => p.BlogId == blogId && p.Url == url); + var post = await (await GetMongoQueryableAsync()).FirstOrDefaultAsync(p => p.BlogId == blogId && p.Url == url); if (post == null) { @@ -48,7 +48,7 @@ namespace Volo.Blogging.Posts public async Task> GetOrderedList(Guid blogId, bool @descending = false) { - var query = GetMongoQueryable().Where(x => x.BlogId == blogId); + var query = (await GetMongoQueryableAsync()).Where(x => x.BlogId == blogId); if (!descending) { diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs index 2c0b3b97bf..f0024b37d7 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs @@ -20,27 +20,27 @@ namespace Volo.Blogging.Tagging public async Task> GetListAsync(Guid blogId) { - return await GetMongoQueryable().Where(t => t.BlogId == blogId).ToListAsync(); + return await (await GetMongoQueryableAsync()).Where(t => t.BlogId == blogId).ToListAsync(); } public async Task GetByNameAsync(Guid blogId, string name) { - return await GetMongoQueryable().Where(t => t.BlogId == blogId && t.Name == name).FirstAsync(); + return await (await GetMongoQueryableAsync()).Where(t => t.BlogId == blogId && t.Name == name).FirstAsync(); } public async Task FindByNameAsync(Guid blogId, string name) { - return await GetMongoQueryable().Where(t => t.BlogId == blogId && t.Name == name).FirstOrDefaultAsync(); + return await (await GetMongoQueryableAsync()).Where(t => t.BlogId == blogId && t.Name == name).FirstOrDefaultAsync(); } public async Task> GetListAsync(IEnumerable ids) { - return await GetMongoQueryable().Where(t => ids.Contains(t.Id)).ToListAsync(); + return await (await GetMongoQueryableAsync()).Where(t => ids.Contains(t.Id)).ToListAsync(); } public async Task DecreaseUsageCountOfTagsAsync(List ids, CancellationToken cancellationToken = default) { - var tags = await GetMongoQueryable() + var tags = await (await GetMongoQueryableAsync()) .Where(t => ids.Contains(t.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Users/MongoBlogUserRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Users/MongoBlogUserRepository.cs index a0b7655946..fdcf4d0097 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Users/MongoBlogUserRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Users/MongoBlogUserRepository.cs @@ -17,7 +17,7 @@ namespace Volo.Blogging.Users public async Task> GetUsersAsync(int maxCount, string filter, CancellationToken cancellationToken) { - var query = GetMongoQueryable(); + var query = await GetMongoQueryableAsync(cancellationToken); if (!string.IsNullOrWhiteSpace(filter)) { diff --git a/modules/cms-kit/docker-compose.override.yml b/modules/cms-kit/docker-compose.override.yml index 94b9df0c22..4cef8f8414 100644 --- a/modules/cms-kit/docker-compose.override.yml +++ b/modules/cms-kit/docker-compose.override.yml @@ -11,19 +11,19 @@ services: identity-server: environment: - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionStrings__Default=Server=sqlserver;Database=CmsKit_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false - - ConnectionStrings__SqlServerCache=Server=sqlserver;Database=CmsKit_Cache;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__Default=Server=sqlserver;Database=CmsKit_Identity;Trusted_Connection=True;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__SqlServerCache=Server=sqlserver;Database=CmsKit_Cache;Trusted_Connection=True;User=sa;Password=yourStrong(!)Password;Integrated Security=false ports: - "51600:80" cms-kit: environment: - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionStrings__Default=Server=sqlserver;Database=CmsKit_ModuleDb;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false - - ConnectionStrings__AbpSettingManagement=Server=sqlserver;Database=CmsKit_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false - - ConnectionStrings__AbpPermissionManagement=Server=sqlserver;Database=CmsKit_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false - - ConnectionStrings__AbpAuditLogging=Server=sqlserver;Database=CmsKit_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false - - ConnectionStrings__SqlServerCache=Server=sqlserver;Database=CmsKit_Cache;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__Default=Server=sqlserver;Database=CmsKit_ModuleDb;Trusted_Connection=True;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__AbpSettingManagement=Server=sqlserver;Database=CmsKit_Identity;Trusted_Connection=True;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__AbpPermissionManagement=Server=sqlserver;Database=CmsKit_Identity;Trusted_Connection=True;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__AbpAuditLogging=Server=sqlserver;Database=CmsKit_Identity;Trusted_Connection=True;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__SqlServerCache=Server=sqlserver;Database=CmsKit_Cache;Trusted_Connection=True;User=sa;Password=yourStrong(!)Password;Integrated Security=false - AuthServer__Authority=http://identity-server ports: - "51601:80" \ No newline at end of file diff --git a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/appsettings.json b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/appsettings.json index 06b66fcede..7811df81cb 100644 --- a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/appsettings.json +++ b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/appsettings.json @@ -3,8 +3,8 @@ "CorsOrigins": "https://*.CmsKit.com,http://localhost:4200" }, "ConnectionStrings": { - "Default": "Server=localhost;Database=CmsKit_Main;Trusted_Connection=True;MultipleActiveResultSets=true", - "CmsKit": "Server=localhost;Database=CmsKit_Module;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=localhost;Database=CmsKit_Main;Trusted_Connection=True", + "CmsKit": "Server=localhost;Database=CmsKit_Module;Trusted_Connection=True" }, "Redis": { "Configuration": "127.0.0.1" diff --git a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/appsettings.json b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/appsettings.json index e0f3118a11..f79959a2e0 100644 --- a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/appsettings.json +++ b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/appsettings.json @@ -5,7 +5,7 @@ }, "AppSelfUrl": "https://localhost:44318/", "ConnectionStrings": { - "Default": "Server=localhost;Database=CmsKit_Main;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=localhost;Database=CmsKit_Main;Trusted_Connection=True" }, "Redis": { "Configuration": "127.0.0.1" diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/appsettings.json b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/appsettings.json index 9b7fd1fa18..417b64b609 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/appsettings.json +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/appsettings.json @@ -1,5 +1,5 @@ { "ConnectionStrings": { - "Default": "Server=localhost;Database=CmsKit_Unified;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=localhost;Database=CmsKit_Unified;Trusted_Connection=True" } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Permissions/CmsKitAdminPermissionDefinitionProvider.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Permissions/CmsKitAdminPermissionDefinitionProvider.cs index 2cb6a53b58..507b1c276f 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Permissions/CmsKitAdminPermissionDefinitionProvider.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Permissions/CmsKitAdminPermissionDefinitionProvider.cs @@ -1,5 +1,7 @@ using Volo.Abp.Authorization.Permissions; +using Volo.Abp.GlobalFeatures; using Volo.Abp.Localization; +using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Localization; namespace Volo.CmsKit.Permissions @@ -10,11 +12,13 @@ namespace Volo.CmsKit.Permissions { var cmsGroup = context.GetGroupOrNull(CmsKitAdminPermissions.GroupName) ?? context.AddGroup(CmsKitAdminPermissions.GroupName, L("Permission:CmsKit")); - cmsGroup - .AddPermission(CmsKitAdminPermissions.Tags.Default, L("Permission:TagManagement")) - .AddChild(CmsKitAdminPermissions.Tags.Create, L("Permission:TagManagement.Create")) - .AddChild(CmsKitAdminPermissions.Tags.Update, L("Permission:TagManagement.Update")) - .AddChild(CmsKitAdminPermissions.Tags.Delete, L("Permission:TagManagement.Delete")); + if (GlobalFeatureManager.Instance.IsEnabled()) + { + var tagGroup = cmsGroup.AddPermission(CmsKitAdminPermissions.Tags.Default, L("Permission:TagManagement")); + tagGroup.AddChild(CmsKitAdminPermissions.Tags.Create, L("Permission:TagManagement.Create")); + tagGroup.AddChild(CmsKitAdminPermissions.Tags.Update, L("Permission:TagManagement.Update")); + tagGroup.AddChild(CmsKitAdminPermissions.Tags.Delete, L("Permission:TagManagement.Delete")); + } } private static LocalizableString L(string name) diff --git a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Comments/EfCoreCommentRepository.cs b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Comments/EfCoreCommentRepository.cs index 9dec7877f8..40496aaef8 100644 --- a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Comments/EfCoreCommentRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Comments/EfCoreCommentRepository.cs @@ -28,8 +28,8 @@ namespace Volo.CmsKit.Comments Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); - var query = from comment in DbSet - join user in DbContext.Set() on comment.CreatorId equals user.Id + var query = from comment in (await GetDbSetAsync()) + join user in (await GetDbContextAsync()).Set() on comment.CreatorId equals user.Id where entityType == comment.EntityType && entityId == comment.EntityId orderby comment.CreationTime select new CommentWithAuthorQueryResultItem @@ -45,7 +45,7 @@ namespace Volo.CmsKit.Comments Comment comment, CancellationToken cancellationToken = default) { - var replies = await DbSet + var replies = await (await GetDbSetAsync()) .Where(x => x.RepliedCommentId == comment.Id) .ToListAsync(GetCancellationToken(cancellationToken)); diff --git a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Pages/EfCorePageRepository.cs b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Pages/EfCorePageRepository.cs index 4502a13b4c..93a7df00d2 100644 --- a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Pages/EfCorePageRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Pages/EfCorePageRepository.cs @@ -23,9 +23,9 @@ namespace Volo.CmsKit.Pages return FindAsync(x => x.Url == url); } - public Task DoesExistAsync(string url) + public async Task DoesExistAsync(string url) { - return DbSet.AnyAsync(x => x.Url == url); + return await (await GetDbSetAsync()).AnyAsync(x => x.Url == url); } } -} \ No newline at end of file +} diff --git a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Ratings/EfCoreRatingRepository.cs b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Ratings/EfCoreRatingRepository.cs index 810335b4d6..a48c288932 100644 --- a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Ratings/EfCoreRatingRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Ratings/EfCoreRatingRepository.cs @@ -24,7 +24,7 @@ namespace Volo.CmsKit.Ratings Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); - var rating = await DbSet.FirstOrDefaultAsync( + var rating = await (await GetDbSetAsync()).FirstOrDefaultAsync( r => r.EntityType == entityType && r.EntityId == entityId && r.CreatorId == userId, GetCancellationToken(cancellationToken)); @@ -38,7 +38,7 @@ namespace Volo.CmsKit.Ratings Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); var query = ( - from rating in DbSet + from rating in (await GetDbSetAsync()) where rating.EntityType == entityType && rating.EntityId == entityId group rating by rating.StarCount into g @@ -54,4 +54,4 @@ namespace Volo.CmsKit.Ratings return ratings; } } -} \ No newline at end of file +} diff --git a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Reactions/EfCoreUserReactionRepository.cs b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Reactions/EfCoreUserReactionRepository.cs index da89de4c74..65824c79b6 100644 --- a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Reactions/EfCoreUserReactionRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Reactions/EfCoreUserReactionRepository.cs @@ -30,7 +30,7 @@ namespace Volo.CmsKit.Reactions Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); Check.NotNullOrWhiteSpace(reactionName, nameof(reactionName)); - return await DbSet + return await (await GetDbSetAsync()) .Where(x => x.CreatorId == userId && x.EntityType == entityType && @@ -48,7 +48,7 @@ namespace Volo.CmsKit.Reactions Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); - return await DbSet + return await (await GetDbSetAsync()) .Where(x => x.CreatorId == userId && x.EntityType == entityType && @@ -64,7 +64,7 @@ namespace Volo.CmsKit.Reactions Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); - return await DbSet + return await (await GetDbSetAsync()) .Where(x => x.EntityType == entityType && x.EntityId == entityId) diff --git a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Tags/EfCoreTagRepository.cs b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Tags/EfCoreTagRepository.cs index 0b6cfe1f48..3d917a059a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Tags/EfCoreTagRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Tags/EfCoreTagRepository.cs @@ -19,13 +19,13 @@ namespace Volo.CmsKit.Tags { } - public virtual Task AnyAsync( + public virtual async Task AnyAsync( [NotNull] string entityType, [NotNull] string name, Guid? tenantId = null, CancellationToken cancellationToken = default) { - return DbSet.AnyAsync(x => + return await (await GetDbSetAsync()).AnyAsync(x => x.EntityType == entityType && x.Name == name && x.TenantId == tenantId, @@ -64,12 +64,12 @@ namespace Volo.CmsKit.Tags Guid? tenantId = null, CancellationToken cancellationToken = default) { - var entityTagIds = await DbContext.Set() + var entityTagIds = await (await GetDbContextAsync()).Set() .Where(q => q.EntityId == entityId && q.TenantId == tenantId) .Select(q => q.TagId) .ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); - var query = DbSet + var query = (await GetDbSetAsync()) .Where(x => x.EntityType == entityType && x.TenantId == tenantId && entityTagIds.Contains(x.Id)); diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs index 9564bcf9f8..5d16c6d55c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs @@ -26,15 +26,15 @@ namespace Volo.CmsKit.MongoDB.Comments Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); - var authorsQuery = from comment in GetMongoQueryable() - join user in DbContext.CmsUsers on comment.CreatorId equals user.Id + var authorsQuery = from comment in (await GetMongoQueryableAsync(cancellationToken)) + join user in (await GetDbContextAsync(cancellationToken)).CmsUsers on comment.CreatorId equals user.Id where entityType == comment.EntityType && entityId == comment.EntityId orderby comment.CreationTime select user; var authors = await authorsQuery.ToListAsync(GetCancellationToken(cancellationToken)); - var comments = await GetMongoQueryable() + var comments = await (await GetMongoQueryableAsync(cancellationToken)) .Where(c => c.EntityId == entityId && c.EntityType == entityType) .OrderBy(c => c.CreationTime) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -53,7 +53,7 @@ namespace Volo.CmsKit.MongoDB.Comments Comment comment, CancellationToken cancellationToken = default) { - var replies = await GetMongoQueryable() + var replies = await (await GetMongoQueryableAsync(cancellationToken)) .Where(x => x.RepliedCommentId == comment.Id) .ToListAsync(GetCancellationToken(cancellationToken)); diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs index e7c6cd32f5..8537500c96 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs @@ -22,10 +22,10 @@ namespace Volo.CmsKit.MongoDB.Pages { return FindAsync(x => x.Url == url); } - - public Task DoesExistAsync(string url) + + public async Task DoesExistAsync(string url) { - return GetMongoQueryable().AnyAsync(x => x.Url == url); + return await (await GetMongoQueryableAsync()).AnyAsync(x => x.Url == url); } } -} \ No newline at end of file +} diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Ratings/MongoRatingRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Ratings/MongoRatingRepository.cs index 92f7f992da..8ff8b4f81d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Ratings/MongoRatingRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Ratings/MongoRatingRepository.cs @@ -25,7 +25,7 @@ namespace Volo.CmsKit.MongoDB.Ratings Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); - var rating = await GetMongoQueryable() + var rating = await (await GetMongoQueryableAsync(cancellationToken)) .FirstOrDefaultAsync(r => r.EntityType == entityType && r.EntityId == entityId && r.CreatorId == userId, GetCancellationToken(cancellationToken)); @@ -39,7 +39,7 @@ namespace Volo.CmsKit.MongoDB.Ratings Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); var query = ( - from rating in GetMongoQueryable() + from rating in (await GetMongoQueryableAsync(cancellationToken)) where rating.EntityType == entityType && rating.EntityId == entityId group rating by rating.StarCount into g @@ -55,4 +55,4 @@ namespace Volo.CmsKit.MongoDB.Ratings return ratings; } } -} \ No newline at end of file +} diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Reactions/MongoUserReactionRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Reactions/MongoUserReactionRepository.cs index e3a09c4514..6ac4cf1b80 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Reactions/MongoUserReactionRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Reactions/MongoUserReactionRepository.cs @@ -29,7 +29,7 @@ namespace Volo.CmsKit.MongoDB.Reactions Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); Check.NotNullOrWhiteSpace(reactionName, nameof(reactionName)); - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(x => x.CreatorId == userId && x.EntityType == entityType && @@ -47,7 +47,7 @@ namespace Volo.CmsKit.MongoDB.Reactions Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(x => x.CreatorId == userId && x.EntityType == entityType && @@ -63,7 +63,7 @@ namespace Volo.CmsKit.MongoDB.Reactions Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(x => x.EntityType == entityType && x.EntityId == entityId) diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoTagRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoTagRepository.cs index 86dc20d83c..02c42c22fb 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoTagRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoTagRepository.cs @@ -18,13 +18,13 @@ namespace Volo.CmsKit.MongoDB.Tags { } - public Task AnyAsync( + public async Task AnyAsync( [NotNull] string entityType, [NotNull] string name, Guid? tenantId = null, CancellationToken cancellationToken = default) { - return GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .AnyAsync(x => x.EntityType == entityType && x.Name == name && @@ -64,13 +64,13 @@ namespace Volo.CmsKit.MongoDB.Tags Guid? tenantId = null, CancellationToken cancellationToken = default) { - var entityTagIds = await DbContext.EntityTags.AsQueryable() + var entityTagIds = await (await GetDbContextAsync(cancellationToken)).EntityTags.AsQueryable() .Where(q => q.EntityId == entityId && q.TenantId == tenantId) .Select(q => q.TagId) .ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); - var query = GetMongoQueryable() - .Where(x => + var query = (await GetMongoQueryableAsync(cancellationToken)) + .Where(x => x.EntityType == entityType && x.TenantId == tenantId && entityTagIds.Contains(x.Id)); diff --git a/modules/docs/app/VoloDocs.Migrator/appsettings.json b/modules/docs/app/VoloDocs.Migrator/appsettings.json index c9934c1e75..8ba3526f59 100644 --- a/modules/docs/app/VoloDocs.Migrator/appsettings.json +++ b/modules/docs/app/VoloDocs.Migrator/appsettings.json @@ -1,3 +1,3 @@ { - "ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True;MultipleActiveResultSets=true" + "ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True" } \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/appsettings.json b/modules/docs/app/VoloDocs.Web/appsettings.json index 8eea6b57cd..b1fb4d82bc 100644 --- a/modules/docs/app/VoloDocs.Web/appsettings.json +++ b/modules/docs/app/VoloDocs.Web/appsettings.json @@ -1,5 +1,5 @@ { - "ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True;MultipleActiveResultSets=true", + "ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True", "LogoUrl": "/assets/images/Logo.png", "ElasticSearch": { "Url": "http://localhost:9200" diff --git a/modules/docs/docker-compose.migrate.yml b/modules/docs/docker-compose.migrate.yml index e88580debd..70142e4ce5 100644 --- a/modules/docs/docker-compose.migrate.yml +++ b/modules/docs/docker-compose.migrate.yml @@ -7,6 +7,6 @@ services: context: ../../ dockerfile: modules/docs/app/VoloDocs.Migrator/Dockerfile environment: - - ConnectionString=Server=sqlserver;Database=VoloDocs;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionString=Server=sqlserver;Database=VoloDocs;Trusted_Connection=True;User=sa;Password=yourStrong(!)Password;Integrated Security=false depends_on: - sqlserver diff --git a/modules/docs/docker-compose.override.yml b/modules/docs/docker-compose.override.yml index 6a8568ce6e..33508c10fe 100644 --- a/modules/docs/docker-compose.override.yml +++ b/modules/docs/docker-compose.override.yml @@ -10,7 +10,7 @@ services: volo-docs: environment: - - ConnectionString=Server=sqlserver;Database=VoloDocs;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionString=Server=sqlserver;Database=VoloDocs;Trusted_Connection=True;User=sa;Password=yourStrong(!)Password;Integrated Security=false - Title=VoloDocs - LogoUrl=/assets/images/Logo.png ports: diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs index f096bc10d9..75420f5500 100644 --- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs @@ -21,7 +21,7 @@ namespace Volo.Docs.Documents public async Task> GetListByProjectId(Guid projectId, CancellationToken cancellationToken = default) { - return await DbSet.Where(d => d.ProjectId == projectId).ToListAsync(cancellationToken: cancellationToken); + return await (await GetDbSetAsync()).Where(d => d.ProjectId == projectId).ToListAsync(cancellationToken: cancellationToken); } public async Task> GetAllAsync( @@ -45,7 +45,7 @@ namespace Volo.Docs.Documents CancellationToken cancellationToken = default) { var query = ApplyFilterForGetAll( - DbSet, + await GetDbSetAsync(), projectId: projectId, name: name, version: version, @@ -87,7 +87,7 @@ namespace Volo.Docs.Documents CancellationToken cancellationToken = default) { var query = ApplyFilterForGetAll( - DbSet, + await GetDbSetAsync(), projectId: projectId, name: name, version: version, @@ -111,7 +111,7 @@ namespace Volo.Docs.Documents bool includeDetails = true, CancellationToken cancellationToken = default) { - return await DbSet.IncludeDetails(includeDetails) + return await (await GetDbSetAsync()).IncludeDetails(includeDetails) .FirstOrDefaultAsync(x => x.ProjectId == projectId && x.Name == name && x.LanguageCode == languageCode && x.Version == version, @@ -127,7 +127,7 @@ namespace Volo.Docs.Documents public async Task GetAsync(Guid id, CancellationToken cancellationToken = default) { - return await DbSet.Where(x => x.Id == id).SingleAsync(cancellationToken: cancellationToken); + return await (await GetDbSetAsync()).Where(x => x.Id == id).SingleAsync(cancellationToken: cancellationToken); } protected virtual IQueryable ApplyFilterForGetAll( @@ -148,7 +148,7 @@ namespace Volo.Docs.Documents DateTime? lastCachedTimeMax, CancellationToken cancellationToken = default) { - return DbSet + return query .WhereIf(projectId.HasValue, d => d.ProjectId == projectId.Value) .WhereIf(name != null, @@ -179,4 +179,4 @@ namespace Volo.Docs.Documents d => d.LastCachedTime.Date <= lastCachedTimeMax.Value.Date); } } -} \ No newline at end of file +} diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Projects/EfCoreProjectRepository.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Projects/EfCoreProjectRepository.cs index 835172e679..bf92a8a795 100644 --- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Projects/EfCoreProjectRepository.cs +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Projects/EfCoreProjectRepository.cs @@ -20,7 +20,7 @@ namespace Volo.Docs.Projects public async Task> GetListAsync(string sorting, int maxResultCount, int skipCount) { - var projects = await DbSet.OrderBy(sorting ?? "Id desc") + var projects = await (await GetDbSetAsync()).OrderBy(sorting ?? "Id desc") .PageBy(skipCount, maxResultCount) .ToListAsync(); @@ -30,8 +30,8 @@ namespace Volo.Docs.Projects public async Task GetByShortNameAsync(string shortName) { var normalizeShortName = NormalizeShortName(shortName); - - var project = await DbSet.FirstOrDefaultAsync(p => p.ShortName == normalizeShortName); + + var project = await (await GetDbSetAsync()).FirstOrDefaultAsync(p => p.ShortName == normalizeShortName); if (project == null) { @@ -44,13 +44,13 @@ namespace Volo.Docs.Projects public async Task ShortNameExistsAsync(string shortName) { var normalizeShortName = NormalizeShortName(shortName); - - return await DbSet.AnyAsync(x => x.ShortName == normalizeShortName); + + return await (await GetDbSetAsync()).AnyAsync(x => x.ShortName == normalizeShortName); } - + private string NormalizeShortName(string shortName) { return shortName.ToLower(); } } -} \ No newline at end of file +} diff --git a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs index b3b5210986..d4b0a1c00e 100644 --- a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs +++ b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs @@ -22,17 +22,17 @@ namespace Volo.Docs.Documents public async Task> GetListByProjectId(Guid projectId, CancellationToken cancellationToken = default) { - return await GetMongoQueryable().Where(d => d.ProjectId == projectId).ToListAsync(cancellationToken); + return await (await GetMongoQueryableAsync(cancellationToken)).Where(d => d.ProjectId == projectId).ToListAsync(cancellationToken); } public async Task FindAsync(Guid projectId, string name, string languageCode, string version, bool includeDetails = true, CancellationToken cancellationToken = default) { - return await GetMongoQueryable().FirstOrDefaultAsync(x => x.ProjectId == projectId && - x.Name == name && - x.LanguageCode == languageCode && - x.Version == version, cancellationToken); + return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.ProjectId == projectId && + x.Name == name && + x.LanguageCode == languageCode && + x.Version == version, cancellationToken); } public async Task DeleteAsync(Guid projectId, string name, string languageCode, string version, @@ -66,7 +66,7 @@ namespace Volo.Docs.Documents return await ApplyFilterForGetAll( - GetMongoQueryable(), + await GetMongoQueryableAsync(cancellationToken), projectId: projectId, name: name, version: version, @@ -110,7 +110,7 @@ namespace Volo.Docs.Documents return await ApplyFilterForGetAll( - GetMongoQueryable(), + await GetMongoQueryableAsync(cancellationToken), projectId: projectId, name: name, version: version, @@ -132,7 +132,7 @@ namespace Volo.Docs.Documents public async Task GetAsync(Guid id, CancellationToken cancellationToken = default) { - return await GetMongoQueryable().Where(x => x.Id == id).SingleAsync(cancellationToken); + return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.Id == id).SingleAsync(cancellationToken); } protected virtual IMongoQueryable ApplyFilterForGetAll( @@ -221,4 +221,4 @@ namespace Volo.Docs.Documents return query; } } -} \ No newline at end of file +} diff --git a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs index f1312b9e5d..91f1af9b2a 100644 --- a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs +++ b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs @@ -21,7 +21,7 @@ namespace Volo.Docs.Projects public async Task> GetListAsync(string sorting, int maxResultCount, int skipCount) { - var projects = await GetMongoQueryable().OrderBy(sorting ?? "Id desc").As>() + var projects = await (await GetMongoQueryableAsync()).OrderBy(sorting ?? "Id desc").As>() .PageBy>(skipCount, maxResultCount) .ToListAsync(); @@ -31,8 +31,8 @@ namespace Volo.Docs.Projects public async Task GetByShortNameAsync(string shortName) { var normalizeShortName = NormalizeShortName(shortName); - - var project = await GetMongoQueryable().FirstOrDefaultAsync(p => p.ShortName == normalizeShortName); + + var project = await (await GetMongoQueryableAsync()).FirstOrDefaultAsync(p => p.ShortName == normalizeShortName); if (project == null) { @@ -45,13 +45,13 @@ namespace Volo.Docs.Projects public async Task ShortNameExistsAsync(string shortName) { var normalizeShortName = NormalizeShortName(shortName); - - return await GetMongoQueryable().AnyAsync(x => x.ShortName == normalizeShortName); + + return await (await GetMongoQueryableAsync()).AnyAsync(x => x.ShortName == normalizeShortName); } - + private string NormalizeShortName(string shortName) { return shortName.ToLower(); } } -} \ No newline at end of file +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo/Abp/FeatureManagement/EntityFrameworkCore/EfCoreFeatureValueRepository.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo/Abp/FeatureManagement/EntityFrameworkCore/EfCoreFeatureValueRepository.cs index c559851bf1..be75e600d8 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo/Abp/FeatureManagement/EntityFrameworkCore/EfCoreFeatureValueRepository.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo/Abp/FeatureManagement/EntityFrameworkCore/EfCoreFeatureValueRepository.cs @@ -17,7 +17,7 @@ namespace Volo.Abp.FeatureManagement.EntityFrameworkCore public virtual async Task FindAsync(string name, string providerName, string providerKey) { - return await DbSet + return await (await GetDbSetAsync()) .OrderBy(x => x.Id) .FirstOrDefaultAsync( s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey @@ -26,7 +26,7 @@ namespace Volo.Abp.FeatureManagement.EntityFrameworkCore public async Task> FindAllAsync(string name, string providerName, string providerKey) { - return await DbSet + return await (await GetDbSetAsync()) .Where( s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey ).ToListAsync(); @@ -34,7 +34,7 @@ namespace Volo.Abp.FeatureManagement.EntityFrameworkCore public virtual async Task> GetListAsync(string providerName, string providerKey) { - return await DbSet + return await (await GetDbSetAsync()) .Where( s => s.ProviderName == providerName && s.ProviderKey == providerKey ).ToListAsync(); diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs index 2b96ca876a..21d4784f6e 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs @@ -18,20 +18,20 @@ namespace Volo.Abp.FeatureManagement.MongoDB public virtual async Task FindAsync(string name, string providerName, string providerKey) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync()) .OrderBy(x => x.Id) .FirstOrDefaultAsync(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey); } public async Task> FindAllAsync(string name, string providerName, string providerKey) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync()) .Where(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey).ToListAsync(); } public virtual async Task> GetListAsync(string providerName, string providerKey) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync()) .Where(s => s.ProviderName == providerName && s.ProviderKey == providerKey) .ToListAsync(); } diff --git a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs index 31c9de0e18..69fae63d71 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs @@ -85,6 +85,7 @@ namespace Volo.Abp.Identity (await UserManager.CreateAsync(user, input.Password)).CheckErrors(); await UpdateUserByInput(user, input); + (await UserManager.UpdateAsync(user)).CheckErrors(); await CurrentUnitOfWork.SaveChangesAsync(); @@ -174,6 +175,7 @@ namespace Volo.Abp.Identity user.Name = input.Name; user.Surname = input.Surname; + (await UserManager.UpdateAsync(user)).CheckErrors(); if (input.RoleNames != null) { diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnit.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnit.cs index 981a0f8fae..53411c1849 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnit.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnit.cs @@ -49,12 +49,13 @@ namespace Volo.Abp.Identity /// /// Initializes a new instance of the class. /// - /// Tenant's Id or null for host. + /// id /// Display name. /// Parent's Id or null if OU is a root. + /// Tenant's Id or null for host. public OrganizationUnit(Guid id, string displayName, Guid? parentId = null, Guid? tenantId = null) + : base(id) { - Id = id; TenantId = tenantId; DisplayName = displayName; ParentId = parentId; diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EFCoreIdentitySecurityLogRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EFCoreIdentitySecurityLogRepository.cs index ddccb3187f..91915cd9b8 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EFCoreIdentitySecurityLogRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EFCoreIdentitySecurityLogRepository.cs @@ -34,7 +34,9 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = false, CancellationToken cancellationToken = default) { - var query = GetListQuery( + cancellationToken = GetCancellationToken(cancellationToken); + + var query = await GetListQueryAsync( startTime, endTime, applicationName, @@ -43,12 +45,13 @@ namespace Volo.Abp.Identity.EntityFrameworkCore userId, userName, clientId, - correlationId + correlationId, + cancellationToken ); return await query.OrderBy(sorting ?? nameof(IdentitySecurityLog.CreationTime) + " desc") .PageBy(skipCount, maxResultCount) - .ToListAsync(GetCancellationToken(cancellationToken)); + .ToListAsync(cancellationToken); } public async Task GetCountAsync( @@ -63,7 +66,9 @@ namespace Volo.Abp.Identity.EntityFrameworkCore string correlationId = null, CancellationToken cancellationToken = default) { - var query = GetListQuery( + cancellationToken = GetCancellationToken(cancellationToken); + + var query = await GetListQueryAsync( startTime, endTime, applicationName, @@ -72,18 +77,21 @@ namespace Volo.Abp.Identity.EntityFrameworkCore userId, userName, clientId, - correlationId + correlationId, + cancellationToken ); - return await query.LongCountAsync(GetCancellationToken(cancellationToken)); + return await query.LongCountAsync(cancellationToken); } public async Task GetByUserIdAsync(Guid id, Guid userId, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await DbSet.OrderBy(x => x.Id).FirstOrDefaultAsync(x => x.Id == id && x.UserId == userId, GetCancellationToken(cancellationToken)); + return await (await GetDbSetAsync()) + .OrderBy(x => x.Id) + .FirstOrDefaultAsync(x => x.Id == id && x.UserId == userId, GetCancellationToken(cancellationToken)); } - protected virtual IQueryable GetListQuery( + protected virtual async Task> GetListQueryAsync( DateTime? startTime = null, DateTime? endTime = null, string applicationName = null, @@ -92,9 +100,10 @@ namespace Volo.Abp.Identity.EntityFrameworkCore Guid? userId = null, string userName = null, string clientId = null, - string correlationId = null) + string correlationId = null, + CancellationToken cancellationToken = default) { - return DbSet.AsNoTracking() + return (await GetDbSetAsync()).AsNoTracking() .WhereIf(startTime.HasValue, securityLog => securityLog.CreationTime >= startTime.Value) .WhereIf(endTime.HasValue, securityLog => securityLog.CreationTime < endTime.Value.AddDays(1).Date) .WhereIf(!applicationName.IsNullOrWhiteSpace(), securityLog => securityLog.ApplicationName == applicationName) diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityClaimTypeRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityClaimTypeRepository.cs index 0d0ff499c1..4cbdfb5725 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityClaimTypeRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityClaimTypeRepository.cs @@ -22,7 +22,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore Guid? ignoredId = null, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .WhereIf(ignoredId != null, ct => ct.Id != ignoredId) .CountAsync(ct => ct.Name == name, GetCancellationToken(cancellationToken)) > 0; } @@ -34,7 +34,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore string filter, CancellationToken cancellationToken = default) { - var identityClaimTypes = await DbSet + var identityClaimTypes = await (await GetDbSetAsync()) .WhereIf( !filter.IsNullOrWhiteSpace(), u => @@ -51,7 +51,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore string filter = null, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .WhereIf( !filter.IsNullOrWhiteSpace(), u => @@ -59,4 +59,4 @@ namespace Volo.Abp.Identity.EntityFrameworkCore ).LongCountAsync(GetCancellationToken(cancellationToken)); } } -} \ No newline at end of file +} diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityLinkUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityLinkUserRepository.cs index 39b62c8f46..6920d1081e 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityLinkUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityLinkUserRepository.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Linq.Dynamic.Core; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; @@ -20,7 +19,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore public async Task FindAsync(IdentityLinkUserInfo sourceLinkUserInfo, IdentityLinkUserInfo targetLinkUserInfo, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .OrderBy(x => x.Id).FirstOrDefaultAsync(x => x.SourceUserId == sourceLinkUserInfo.UserId && x.SourceTenantId == sourceLinkUserInfo.TenantId && x.TargetUserId == targetLinkUserInfo.UserId && x.TargetTenantId == targetLinkUserInfo.TenantId || @@ -31,7 +30,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore public async Task> GetListAsync(IdentityLinkUserInfo linkUserInfo, CancellationToken cancellationToken = default) { - return await DbSet.Where(x => + return await (await GetDbSetAsync()) + .Where(x => x.SourceUserId == linkUserInfo.UserId && x.SourceTenantId == linkUserInfo.TenantId || x.TargetUserId == linkUserInfo.UserId && x.TargetTenantId == linkUserInfo.TenantId) .ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs index bb17d863aa..b1389afd6a 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs @@ -22,7 +22,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = true, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .OrderBy(x => x.Id) .FirstOrDefaultAsync(r => r.NormalizedName == normalizedRoleName, GetCancellationToken(cancellationToken)); @@ -36,7 +36,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = true, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || @@ -50,7 +50,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore IEnumerable ids, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .Where(t => ids.Contains(t.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -58,23 +58,32 @@ namespace Volo.Abp.Identity.EntityFrameworkCore public virtual async Task> GetDefaultOnesAsync( bool includeDetails = false, CancellationToken cancellationToken = default) { - return await DbSet.IncludeDetails(includeDetails).Where(r => r.IsDefault).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetDbSetAsync()) + .IncludeDetails(includeDetails) + .Where(r => r.IsDefault) + .ToListAsync(GetCancellationToken(cancellationToken)); } public async Task GetCountAsync( string filter = null, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.NormalizedName.Contains(filter)) .LongCountAsync(GetCancellationToken(cancellationToken)); } + [Obsolete("Use WithDetailsAsync")] public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); } + + public override async Task> WithDetailsAsync() + { + return (await GetQueryableAsync()).IncludeDetails(); + } } } diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs index f5d8fd2bb5..8fcce7c35a 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs @@ -6,7 +6,6 @@ using System.Security.Claims; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Internal; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; @@ -24,7 +23,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = true, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .OrderBy(x => x.Id) .FirstOrDefaultAsync( @@ -37,20 +36,21 @@ namespace Volo.Abp.Identity.EntityFrameworkCore Guid id, CancellationToken cancellationToken = default) { - var query = from userRole in DbContext.Set() - join role in DbContext.Roles on userRole.RoleId equals role.Id + var dbContext = await GetDbContextAsync(); + var query = from userRole in dbContext.Set() + join role in dbContext.Roles on userRole.RoleId equals role.Id where userRole.UserId == id select role.Name; - var organizationUnitIds = DbContext.Set().Where(q => q.UserId == id).Select(q => q.OrganizationUnitId).ToArray(); + var organizationUnitIds = dbContext.Set().Where(q => q.UserId == id).Select(q => q.OrganizationUnitId).ToArray(); var organizationRoleIds = await ( - from ouRole in DbContext.Set() - join ou in DbContext.Set() on ouRole.OrganizationUnitId equals ou.Id + from ouRole in dbContext.Set() + join ou in dbContext.Set() on ouRole.OrganizationUnitId equals ou.Id where organizationUnitIds.Contains(ouRole.OrganizationUnitId) select ouRole.RoleId ).ToListAsync(GetCancellationToken(cancellationToken)); - var orgUnitRoleNameQuery = DbContext.Roles.Where(r => organizationRoleIds.Contains(r.Id)).Select(n => n.Name); + var orgUnitRoleNameQuery = dbContext.Roles.Where(r => organizationRoleIds.Contains(r.Id)).Select(n => n.Name); var resultQuery = query.Union(orgUnitRoleNameQuery); return await resultQuery.ToListAsync(GetCancellationToken(cancellationToken)); } @@ -59,10 +59,11 @@ namespace Volo.Abp.Identity.EntityFrameworkCore Guid id, CancellationToken cancellationToken = default) { - var query = from userOu in DbContext.Set() - join roleOu in DbContext.Set() on userOu.OrganizationUnitId equals roleOu.OrganizationUnitId - join ou in DbContext.Set() on roleOu.OrganizationUnitId equals ou.Id - join userOuRoles in DbContext.Roles on roleOu.RoleId equals userOuRoles.Id + var dbContext = await GetDbContextAsync(); + var query = from userOu in dbContext.Set() + join roleOu in dbContext.Set() on userOu.OrganizationUnitId equals roleOu.OrganizationUnitId + join ou in dbContext.Set() on roleOu.OrganizationUnitId equals ou.Id + join userOuRoles in dbContext.Roles on roleOu.RoleId equals userOuRoles.Id where userOu.UserId == id select userOuRoles.Name; @@ -77,7 +78,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = true, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .Where(u => u.Logins.Any(login => login.LoginProvider == loginProvider && login.ProviderKey == providerKey)) .OrderBy(x=>x.Id) @@ -89,7 +90,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = true, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .OrderBy(x => x.Id) .FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail, GetCancellationToken(cancellationToken)); @@ -100,7 +101,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = false, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .Where(u => u.Claims.Any(c => c.ClaimType == claim.Type && c.ClaimValue == claim.Value)) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -111,7 +112,9 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = false, CancellationToken cancellationToken = default) { - var role = await DbContext.Roles + var dbContext = await GetDbContextAsync(); + + var role = await dbContext.Roles .Where(x => x.NormalizedName == normalizedRoleName) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -121,7 +124,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore return new List(); } - return await DbSet + return await dbContext.Users .IncludeDetails(includeDetails) .Where(u => u.Roles.Any(r => r.RoleId == role.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -135,7 +138,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = false, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .WhereIf( !filter.IsNullOrWhiteSpace(), @@ -156,24 +159,26 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = false, CancellationToken cancellationToken = default) { - var query = from userRole in DbContext.Set() - join role in DbContext.Roles.IncludeDetails(includeDetails) on userRole.RoleId equals role.Id + var dbContext = await GetDbContextAsync(); + + var query = from userRole in dbContext.Set() + join role in dbContext.Roles.IncludeDetails(includeDetails) on userRole.RoleId equals role.Id where userRole.UserId == id select role; //TODO: Needs improvement - var userOrganizationsQuery = from userOrg in DbContext.Set() - join ou in DbContext.OrganizationUnits.IncludeDetails(includeDetails) on userOrg.OrganizationUnitId equals ou.Id + var userOrganizationsQuery = from userOrg in dbContext.Set() + join ou in dbContext.OrganizationUnits.IncludeDetails(includeDetails) on userOrg.OrganizationUnitId equals ou.Id where userOrg.UserId == id select ou; - var orgUserRoleQuery = DbContext.Set() + var orgUserRoleQuery = dbContext.Set() .Where(q => userOrganizationsQuery .Select(t => t.Id) .Contains(q.OrganizationUnitId)) .Select(t => t.RoleId); - var orgRoles = DbContext.Roles.Where(q => orgUserRoleQuery.Contains(q.Id)); + var orgRoles = dbContext.Roles.Where(q => orgUserRoleQuery.Contains(q.Id)); var resultQuery = query.Union(orgRoles); return await resultQuery.ToListAsync(GetCancellationToken(cancellationToken)); @@ -183,7 +188,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore string filter = null, CancellationToken cancellationToken = default) { - return await this.WhereIf( + return await (await GetDbSetAsync()) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.UserName.Contains(filter) || @@ -200,9 +206,11 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = false, CancellationToken cancellationToken = default) { - var query = from userOU in DbContext.Set() - join ou in DbContext.OrganizationUnits.IncludeDetails(includeDetails) on userOU.OrganizationUnitId equals ou.Id - where userOU.UserId == id + var dbContext = await GetDbContextAsync(); + + var query = from userOu in dbContext.Set() + join ou in dbContext.OrganizationUnits.IncludeDetails(includeDetails) on userOu.OrganizationUnitId equals ou.Id + where userOu.UserId == id select ou; return await query.ToListAsync(GetCancellationToken(cancellationToken)); @@ -213,10 +221,13 @@ namespace Volo.Abp.Identity.EntityFrameworkCore CancellationToken cancellationToken = default ) { - var query = from userOu in DbContext.Set() - join user in DbSet on userOu.UserId equals user.Id + var dbContext = await GetDbContextAsync(); + + var query = from userOu in dbContext.Set() + join user in dbContext.Users on userOu.UserId equals user.Id where userOu.OrganizationUnitId == organizationUnitId select user; + return await query.ToListAsync(GetCancellationToken(cancellationToken)); } @@ -225,10 +236,13 @@ namespace Volo.Abp.Identity.EntityFrameworkCore CancellationToken cancellationToken = default ) { - var query = from userOu in DbContext.Set() - join user in DbSet on userOu.UserId equals user.Id + var dbContext = await GetDbContextAsync(); + + var query = from userOu in dbContext.Set() + join user in dbContext.Users on userOu.UserId equals user.Id where organizationUnitIds.Contains(userOu.OrganizationUnitId) select user; + return await query.ToListAsync(GetCancellationToken(cancellationToken)); } @@ -237,17 +251,26 @@ namespace Volo.Abp.Identity.EntityFrameworkCore CancellationToken cancellationToken = default ) { - var query = from userOu in DbContext.Set() - join user in DbSet on userOu.UserId equals user.Id - join ou in DbContext.Set() on userOu.OrganizationUnitId equals ou.Id + var dbContext = await GetDbContextAsync(); + + var query = from userOu in dbContext.Set() + join user in dbContext.Users on userOu.UserId equals user.Id + join ou in dbContext.Set() on userOu.OrganizationUnitId equals ou.Id where ou.Code.StartsWith(code) select user; + return await query.ToListAsync(GetCancellationToken(cancellationToken)); } + [Obsolete("Use WithDetailsAsync method.")] public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); } + + public override async Task> WithDetailsAsync() + { + return (await GetQueryableAsync()).IncludeDetails(); + } } } diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs index d63d7a2228..6a54f41959 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq.Dynamic.Core; using System.Linq; +using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; @@ -25,7 +26,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = false, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .Where(x => x.ParentId == parentId) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -37,7 +38,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = false, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId.Value) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -50,7 +51,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = true, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .OrderBy(sorting ?? nameof(OrganizationUnit.DisplayName)) .PageBy(skipCount, maxResultCount) @@ -62,7 +63,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = false, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .Where(t => ids.Contains(t.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -73,7 +74,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = true, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .OrderBy(x => x.Id) .FirstOrDefaultAsync( @@ -90,10 +91,13 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = false, CancellationToken cancellationToken = default) { - var query = from organizationRole in DbContext.Set() - join role in DbContext.Roles.IncludeDetails(includeDetails) on organizationRole.RoleId equals role.Id + var dbContext = await GetDbContextAsync(); + + var query = from organizationRole in dbContext.Set() + join role in dbContext.Roles.IncludeDetails(includeDetails) on organizationRole.RoleId equals role.Id where organizationRole.OrganizationUnitId == organizationUnit.Id select role; + query = query .OrderBy(sorting ?? nameof(IdentityRole.Name)) .PageBy(skipCount, maxResultCount); @@ -105,8 +109,10 @@ namespace Volo.Abp.Identity.EntityFrameworkCore OrganizationUnit organizationUnit, CancellationToken cancellationToken = default) { - var query = from organizationRole in DbContext.Set() - join role in DbContext.Roles on organizationRole.RoleId equals role.Id + var dbContext = await GetDbContextAsync(); + + var query = from organizationRole in dbContext.Set() + join role in dbContext.Roles on organizationRole.RoleId equals role.Id where organizationRole.OrganizationUnitId == organizationUnit.Id select role; @@ -123,8 +129,9 @@ namespace Volo.Abp.Identity.EntityFrameworkCore CancellationToken cancellationToken = default) { var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToList(); + var dbContext = await GetDbContextAsync(); - return await DbContext.Roles + return await dbContext.Roles .Where(r => !roleIds.Contains(r.Id)) .IncludeDetails(includeDetails) .WhereIf(!filter.IsNullOrWhiteSpace(), r => r.Name.Contains(filter)) @@ -139,8 +146,9 @@ namespace Volo.Abp.Identity.EntityFrameworkCore CancellationToken cancellationToken = default) { var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToList(); + var dbContext = await GetDbContextAsync(); - return await DbContext.Roles + return await dbContext.Roles .Where(r => !roleIds.Contains(r.Id)) .WhereIf(!filter.IsNullOrWhiteSpace(), r => r.Name.Contains(filter)) .CountAsync(cancellationToken); @@ -155,7 +163,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = false, CancellationToken cancellationToken = default) { - var query = CreateGetMembersFilteredQuery(organizationUnit, filter); + var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, filter); return await query.IncludeDetails(includeDetails).OrderBy(sorting ?? nameof(IdentityUser.UserName)) .PageBy(skipCount, maxResultCount) @@ -167,7 +175,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore string filter = null, CancellationToken cancellationToken = default) { - var query = CreateGetMembersFilteredQuery(organizationUnit, filter); + var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, filter); return await query.CountAsync(GetCancellationToken(cancellationToken)); } @@ -181,11 +189,13 @@ namespace Volo.Abp.Identity.EntityFrameworkCore bool includeDetails = false, CancellationToken cancellationToken = default) { - var userIdsInOrganizationUnit = DbContext.Set() + var dbContext = await GetDbContextAsync(); + + var userIdsInOrganizationUnit = dbContext.Set() .Where(uou => uou.OrganizationUnitId == organizationUnit.Id) .Select(uou => uou.UserId); - var query = DbContext.Users + var query = dbContext.Users .Where(u => !userIdsInOrganizationUnit.Contains(u.Id)); if (!filter.IsNullOrWhiteSpace()) @@ -209,11 +219,13 @@ namespace Volo.Abp.Identity.EntityFrameworkCore string filter = null, CancellationToken cancellationToken = default) { - var userIdsInOrganizationUnit = DbContext.Set() + var dbContext = await GetDbContextAsync(); + + var userIdsInOrganizationUnit = dbContext.Set() .Where(uou => uou.OrganizationUnitId == organizationUnit.Id) .Select(uou => uou.UserId); - return await DbContext.Users + return await dbContext.Users .Where(u => !userIdsInOrganizationUnit.Contains(u.Id)) .WhereIf(!filter.IsNullOrWhiteSpace(), u => u.UserName.Contains(filter) || @@ -222,11 +234,17 @@ namespace Volo.Abp.Identity.EntityFrameworkCore .CountAsync(cancellationToken); } + [Obsolete("Use WithDetailsAsync method.")] public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); } + public override async Task> WithDetailsAsync() + { + return (await GetQueryableAsync()).IncludeDetails(); + } + public virtual Task RemoveAllRolesAsync( OrganizationUnit organizationUnit, CancellationToken cancellationToken = default) @@ -239,17 +257,21 @@ namespace Volo.Abp.Identity.EntityFrameworkCore OrganizationUnit organizationUnit, CancellationToken cancellationToken = default) { - var ouMembersQuery = await DbContext.Set() + var dbContext = await GetDbContextAsync(); + + var ouMembersQuery = await dbContext.Set() .Where(q => q.OrganizationUnitId == organizationUnit.Id) .ToListAsync(GetCancellationToken(cancellationToken)); - DbContext.Set().RemoveRange(ouMembersQuery); + dbContext.Set().RemoveRange(ouMembersQuery); } - protected virtual IQueryable CreateGetMembersFilteredQuery(OrganizationUnit organizationUnit, string filter = null) + protected virtual async Task> CreateGetMembersFilteredQueryAsync(OrganizationUnit organizationUnit, string filter = null) { - var query = from userOu in DbContext.Set() - join user in DbContext.Users on userOu.UserId equals user.Id + var dbContext = await GetDbContextAsync(); + + var query = from userOu in dbContext.Set() + join user in dbContext.Users on userOu.UserId equals user.Id where userOu.OrganizationUnitId == organizationUnit.Id select user; diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs index a123868799..6795735793 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs @@ -24,13 +24,13 @@ namespace Volo.Abp.Identity.MongoDB { if (ignoredId == null) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(ct => ct.Name == name) .AnyAsync(GetCancellationToken(cancellationToken)); } else { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(ct => ct.Id != ignoredId && ct.Name == name) .AnyAsync(GetCancellationToken(cancellationToken)); } @@ -43,7 +43,7 @@ namespace Volo.Abp.Identity.MongoDB string filter, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .WhereIf>( !filter.IsNullOrWhiteSpace(), u => @@ -59,7 +59,7 @@ namespace Volo.Abp.Identity.MongoDB string filter = null, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .WhereIf>( !filter.IsNullOrWhiteSpace(), u => diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs index 6e8d53821b..43bad94271 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs @@ -19,7 +19,7 @@ namespace Volo.Abp.Identity.MongoDB public async Task FindAsync(IdentityLinkUserInfo sourceLinkUserInfo, IdentityLinkUserInfo targetLinkUserInfo, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .OrderBy(x => x.Id).FirstOrDefaultAsync(x => x.SourceUserId == sourceLinkUserInfo.UserId && x.SourceTenantId == sourceLinkUserInfo.TenantId && x.TargetUserId == targetLinkUserInfo.UserId && x.TargetTenantId == targetLinkUserInfo.TenantId || @@ -30,7 +30,7 @@ namespace Volo.Abp.Identity.MongoDB public async Task> GetListAsync(IdentityLinkUserInfo linkUserInfo, CancellationToken cancellationToken = default) { - return await GetMongoQueryable().Where(x => + return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.SourceUserId == linkUserInfo.UserId && x.SourceTenantId == linkUserInfo.TenantId || x.TargetUserId == linkUserInfo.UserId && x.TargetTenantId == linkUserInfo.TenantId) .ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs index 9c6bccf74f..0731008f57 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs @@ -23,7 +23,7 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = true, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync(r => r.NormalizedName == normalizedRoleName, GetCancellationToken(cancellationToken)); } @@ -36,7 +36,7 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.NormalizedName.Contains(filter)) @@ -50,7 +50,7 @@ namespace Volo.Abp.Identity.MongoDB IEnumerable ids, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(t => ids.Contains(t.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -59,14 +59,16 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable().Where(r => r.IsDefault).ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); + return await (await GetMongoQueryableAsync(cancellationToken)) + .Where(r => r.IsDefault) + .ToListAsync(GetCancellationToken(cancellationToken)); } public async Task GetCountAsync( string filter = null, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.NormalizedName.Contains(filter)) diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySecurityLogRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySecurityLogRepository.cs index b63a6001f9..a0a8b9b103 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySecurityLogRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySecurityLogRepository.cs @@ -35,7 +35,7 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - var query = GetListQuery( + var query = await GetListQueryAsync( startTime, endTime, applicationName, @@ -65,7 +65,7 @@ namespace Volo.Abp.Identity.MongoDB string correlationId = null, CancellationToken cancellationToken = default) { - var query = GetListQuery( + var query = await GetListQueryAsync( startTime, endTime, applicationName, @@ -85,11 +85,11 @@ namespace Volo.Abp.Identity.MongoDB public async Task GetByUserIdAsync(Guid id, Guid userId, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable().OrderBy(x => x.Id).FirstOrDefaultAsync(x => x.Id == id && x.UserId == userId, + return await (await GetMongoQueryableAsync(cancellationToken)).OrderBy(x => x.Id).FirstOrDefaultAsync(x => x.Id == id && x.UserId == userId, GetCancellationToken(cancellationToken)); } - protected virtual IQueryable GetListQuery( + protected virtual async Task> GetListQueryAsync( DateTime? startTime = null, DateTime? endTime = null, string applicationName = null, @@ -100,7 +100,7 @@ namespace Volo.Abp.Identity.MongoDB string clientId = null, string correlationId = null) { - return GetMongoQueryable() + return (await GetMongoQueryableAsync()) .WhereIf(startTime.HasValue, securityLog => securityLog.CreationTime >= startTime.Value) .WhereIf(endTime.HasValue, securityLog => securityLog.CreationTime < endTime.Value.AddDays(1).Date) .WhereIf(!applicationName.IsNullOrWhiteSpace(), diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs index 692e5d5016..0864f7b01c 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs @@ -24,7 +24,7 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = true, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync( u => u.NormalizedUserName == normalizedUserName, @@ -40,14 +40,17 @@ namespace Volo.Abp.Identity.MongoDB var organizationUnitIds = user.OrganizationUnits .Select(r => r.OrganizationUnitId) .ToArray(); - var organizationUnits = DbContext.OrganizationUnits + + var dbContext = await GetDbContextAsync(cancellationToken); + + var organizationUnits = dbContext.OrganizationUnits .AsQueryable() .Where(ou => organizationUnitIds.Contains(ou.Id)) .ToArray(); var orgUnitRoleIds = organizationUnits.SelectMany(x => x.Roles.Select(r => r.RoleId)).ToArray(); var roleIds = user.Roles.Select(r => r.RoleId).ToArray(); var allRoleIds = orgUnitRoleIds.Union(roleIds); - return await DbContext.Roles.AsQueryable().Where(r => allRoleIds.Contains(r.Id)).Select(r => r.Name).ToListAsync(GetCancellationToken(cancellationToken)); + return await dbContext.Roles.AsQueryable().Where(r => allRoleIds.Contains(r.Id)).Select(r => r.Name).ToListAsync(GetCancellationToken(cancellationToken)); } public async Task> GetRoleNamesInOrganizationUnitAsync( @@ -60,14 +63,16 @@ namespace Volo.Abp.Identity.MongoDB .Select(r => r.OrganizationUnitId) .ToArray(); - var organizationUnits = DbContext.OrganizationUnits + var dbContext = await GetDbContextAsync(cancellationToken); + + var organizationUnits = dbContext.OrganizationUnits .AsQueryable() .Where(ou => organizationUnitIds.Contains(ou.Id)) .ToArray(); var roleIds = organizationUnits.SelectMany(x => x.Roles.Select(r => r.RoleId)).ToArray(); - return await DbContext.Roles //TODO: Such usage suppress filters! + return await dbContext.Roles //TODO: Such usage suppress filters! .AsQueryable() .Where(r => roleIds.Contains(r.Id)) .Select(r => r.Name) @@ -80,7 +85,7 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = true, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(u => u.Logins.Any(login => login.LoginProvider == loginProvider && login.ProviderKey == providerKey)) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -91,7 +96,7 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = true, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .OrderBy(x => x.Id).FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail, GetCancellationToken(cancellationToken)); } @@ -100,7 +105,7 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(u => u.Claims.Any(c => c.ClaimType == claim.Type && c.ClaimValue == claim.Value)) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -110,19 +115,21 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - var role = await DbContext.Roles.AsQueryable() + cancellationToken = GetCancellationToken(cancellationToken); + + var role = await (await GetDbContextAsync(cancellationToken)).Roles.AsQueryable() //TODO: Such usages breaks data filters .Where(x => x.NormalizedName == normalizedRoleName) .OrderBy(x => x.Id) - .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); + .FirstOrDefaultAsync(cancellationToken); if (role == null) { return new List(); } - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(u => u.Roles.Any(r => r.RoleId == role.Id)) - .ToListAsync(GetCancellationToken(cancellationToken)); + .ToListAsync(cancellationToken); } public virtual async Task> GetListAsync( @@ -133,7 +140,7 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .WhereIf>( !filter.IsNullOrWhiteSpace(), u => @@ -158,14 +165,17 @@ namespace Volo.Abp.Identity.MongoDB var organizationUnitIds = user.OrganizationUnits .Select(r => r.OrganizationUnitId) .ToArray(); - var organizationUnits = DbContext.OrganizationUnits + + var dbContext = await GetDbContextAsync(cancellationToken); + + var organizationUnits = dbContext.OrganizationUnits .AsQueryable() .Where(ou => organizationUnitIds.Contains(ou.Id)) .ToArray(); var orgUnitRoleIds = organizationUnits.SelectMany(x => x.Roles.Select(r => r.RoleId)).ToArray(); var roleIds = user.Roles.Select(r => r.RoleId).ToArray(); var allRoleIds = orgUnitRoleIds.Union(roleIds); - return await DbContext.Roles.AsQueryable().Where(r => allRoleIds.Contains(r.Id)).ToListAsync(GetCancellationToken(cancellationToken)); + return await dbContext.Roles.AsQueryable().Where(r => allRoleIds.Contains(r.Id)).ToListAsync(GetCancellationToken(cancellationToken)); } public async Task> GetOrganizationUnitsAsync( @@ -175,17 +185,19 @@ namespace Volo.Abp.Identity.MongoDB { var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken)); var organizationUnitIds = user.OrganizationUnits.Select(r => r.OrganizationUnitId); - return await DbContext.OrganizationUnits.AsQueryable() + + var dbContext = await GetDbContextAsync(cancellationToken); + + return await dbContext.OrganizationUnits.AsQueryable() .Where(ou => organizationUnitIds.Contains(ou.Id)) - .ToListAsync(GetCancellationToken(cancellationToken)) - ; + .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync( string filter = null, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .WhereIf>( !filter.IsNullOrWhiteSpace(), u => @@ -202,7 +214,7 @@ namespace Volo.Abp.Identity.MongoDB Guid organizationUnitId, CancellationToken cancellationToken = default) { - var result = await GetMongoQueryable() + var result = await (await GetMongoQueryableAsync(cancellationToken)) .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnitId)) .ToListAsync(GetCancellationToken(cancellationToken)) ; @@ -213,7 +225,7 @@ namespace Volo.Abp.Identity.MongoDB List organizationUnitIds, CancellationToken cancellationToken = default) { - var result = await GetMongoQueryable() + var result = await (await GetMongoQueryableAsync(cancellationToken)) .Where(u => u.OrganizationUnits.Any(uou => organizationUnitIds.Contains(uou.OrganizationUnitId))) .ToListAsync(GetCancellationToken(cancellationToken)) ; @@ -224,16 +236,17 @@ namespace Volo.Abp.Identity.MongoDB string code, CancellationToken cancellationToken = default) { - var organizationUnitIds = await DbContext.OrganizationUnits.AsQueryable() + cancellationToken = GetCancellationToken(cancellationToken); + + var organizationUnitIds = await (await GetDbContextAsync(cancellationToken)).OrganizationUnits.AsQueryable() .Where(ou => ou.Code.StartsWith(code)) .Select(ou => ou.Id) - .ToListAsync(GetCancellationToken(cancellationToken)) + .ToListAsync(cancellationToken) ; - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(u => u.OrganizationUnits.Any(uou => organizationUnitIds.Contains(uou.OrganizationUnitId))) - .ToListAsync(GetCancellationToken(cancellationToken)) - ; + .ToListAsync(cancellationToken); } } } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs index bd4b079a07..de0afd8abc 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs @@ -1,9 +1,7 @@ -using MongoDB.Bson; -using MongoDB.Driver; +using MongoDB.Driver; using MongoDB.Driver.Linq; using System; using System.Collections.Generic; -using System.Data; using System.Linq; using System.Linq.Dynamic.Core; using System.Threading; @@ -11,7 +9,6 @@ using System.Threading.Tasks; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.MongoDB; using Volo.Abp.MultiTenancy; -using Volo.Abp.Uow; namespace Volo.Abp.Identity.MongoDB { @@ -30,7 +27,7 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(ou => ou.ParentId == parentId) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -41,7 +38,7 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId.Value) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -51,7 +48,7 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(t => ids.Contains(t.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -63,7 +60,7 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .OrderBy(sorting ?? nameof(OrganizationUnit.DisplayName)) .As>() .PageBy>(skipCount, maxResultCount) @@ -75,7 +72,7 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = true, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync( ou => ou.DisplayName == displayName, @@ -92,7 +89,10 @@ namespace Volo.Abp.Identity.MongoDB CancellationToken cancellationToken = default) { var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); - return await ApplyDataFilters, IdentityRole>(DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id))) + var dbContext = await GetDbContextAsync(cancellationToken); + return await ApplyDataFilters, IdentityRole>( + dbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)) + ) .OrderBy(sorting ?? nameof(IdentityRole.Name)) .As>() .PageBy>(skipCount, maxResultCount) @@ -104,7 +104,10 @@ namespace Volo.Abp.Identity.MongoDB CancellationToken cancellationToken = default) { var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); - return await ApplyDataFilters, IdentityRole>( DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id))) + var dbContext = await GetDbContextAsync(cancellationToken); + return await ApplyDataFilters, IdentityRole>( + dbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)) + ) .As>() .CountAsync(cancellationToken); } @@ -119,7 +122,8 @@ namespace Volo.Abp.Identity.MongoDB CancellationToken cancellationToken = default) { var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); - return await ApplyDataFilters, IdentityRole>(DbContext.Roles.AsQueryable()) + var dbContext = await GetDbContextAsync(cancellationToken); + return await ApplyDataFilters, IdentityRole>(dbContext.Roles.AsQueryable()) .Where(r => !roleIds.Contains(r.Id)) .WhereIf(!filter.IsNullOrWhiteSpace(), r => r.Name.Contains(filter)) .OrderBy(sorting ?? nameof(IdentityRole.Name)) @@ -134,7 +138,8 @@ namespace Volo.Abp.Identity.MongoDB CancellationToken cancellationToken = default) { var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); - return await ApplyDataFilters, IdentityRole>(DbContext.Roles.AsQueryable()) + var dbContext = await GetDbContextAsync(cancellationToken); + return await ApplyDataFilters, IdentityRole>(dbContext.Roles.AsQueryable()) .Where(r => !roleIds.Contains(r.Id)) .WhereIf(!filter.IsNullOrWhiteSpace(), r => r.Name.Contains(filter)) .As>() @@ -150,13 +155,13 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - var query = CreateGetMembersFilteredQuery(organizationUnit, filter); - + cancellationToken = GetCancellationToken(cancellationToken); + var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, filter, cancellationToken); return await query .OrderBy(sorting ?? nameof(IdentityUser.UserName)) .As>() .PageBy>(skipCount, maxResultCount) - .ToListAsync(GetCancellationToken(cancellationToken)); + .ToListAsync(cancellationToken); } public virtual async Task GetMembersCountAsync( @@ -164,9 +169,9 @@ namespace Volo.Abp.Identity.MongoDB string filter = null, CancellationToken cancellationToken = default) { - var query = CreateGetMembersFilteredQuery(organizationUnit, filter); - - return await query.CountAsync(GetCancellationToken(cancellationToken)); + cancellationToken = GetCancellationToken(cancellationToken); + var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, filter, cancellationToken); + return await query.CountAsync(cancellationToken); } public async Task> GetUnaddedUsersAsync( @@ -178,7 +183,8 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - return await ApplyDataFilters, IdentityUser>(DbContext.Users.AsQueryable()) + var dbContext = await GetDbContextAsync(cancellationToken); + return await ApplyDataFilters, IdentityUser>(dbContext.Users.AsQueryable()) .Where(u => !u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) .WhereIf>( !filter.IsNullOrWhiteSpace(), @@ -196,7 +202,8 @@ namespace Volo.Abp.Identity.MongoDB public async Task GetUnaddedUsersCountAsync(OrganizationUnit organizationUnit, string filter = null, CancellationToken cancellationToken = default) { - return await ApplyDataFilters, IdentityUser>(DbContext.Users.AsQueryable()) + var dbContext = await GetDbContextAsync(cancellationToken); + return await ApplyDataFilters, IdentityUser>(dbContext.Users.AsQueryable()) .Where(u => !u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) .WhereIf>( !filter.IsNullOrWhiteSpace(), @@ -217,7 +224,8 @@ namespace Volo.Abp.Identity.MongoDB public virtual async Task RemoveAllMembersAsync(OrganizationUnit organizationUnit, CancellationToken cancellationToken = default) { - var users = await ApplyDataFilters, IdentityUser>(DbContext.Users.AsQueryable()) + var dbContext = await GetDbContextAsync(cancellationToken); + var users = await ApplyDataFilters, IdentityUser>(dbContext.Users.AsQueryable()) .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) .As>() .ToListAsync(GetCancellationToken(cancellationToken)); @@ -225,13 +233,17 @@ namespace Volo.Abp.Identity.MongoDB foreach (var user in users) { user.RemoveOrganizationUnit(organizationUnit.Id); - DbContext.Users.ReplaceOne(u => u.Id == user.Id, user); + await dbContext.Users.ReplaceOneAsync(u => u.Id == user.Id, user, cancellationToken: cancellationToken); } } - protected virtual IMongoQueryable CreateGetMembersFilteredQuery(OrganizationUnit organizationUnit, string filter = null) + protected virtual async Task> CreateGetMembersFilteredQueryAsync( + OrganizationUnit organizationUnit, + string filter = null, + CancellationToken cancellationToken = default) { - return ApplyDataFilters, IdentityUser>(DbContext.Users.AsQueryable()) + var dbContext = await GetDbContextAsync(cancellationToken); + return ApplyDataFilters, IdentityUser>(dbContext.Users.AsQueryable()) .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) .WhereIf>( !filter.IsNullOrWhiteSpace(), diff --git a/modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RoleDeletedEventHandler.cs b/modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RoleDeletedEventHandler.cs new file mode 100644 index 0000000000..b3fd565b24 --- /dev/null +++ b/modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RoleDeletedEventHandler.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Entities.Events; +using Volo.Abp.EventBus; +using Volo.Abp.Identity; + +namespace Volo.Abp.PermissionManagement.Identity +{ + // public class RoleDeletedEventHandler : + // ILocalEventHandler>, + // ITransientDependency + // { + // protected IPermissionManager PermissionManager { get; } + // + // public RoleDeletedEventHandler(IPermissionManager permissionManager) + // { + // PermissionManager = permissionManager; + // } + // + // public virtual async Task HandleEventAsync(EntityDeletedEventData eventData) + // { + // await PermissionManager.DeleteAsync(RolePermissionValueProvider.ProviderName, eventData.Entity.Name); + // } + // } +} diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/ApiResources/ApiResourceRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/ApiResources/ApiResourceRepository.cs index 3cdcb7e49d..16a789048d 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/ApiResources/ApiResourceRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/ApiResources/ApiResourceRepository.cs @@ -20,7 +20,7 @@ namespace Volo.Abp.IdentityServer.ApiResources public async Task FindByNameAsync(string apiResourceName, bool includeDetails = true, CancellationToken cancellationToken = default) { - var query = from apiResource in DbSet.IncludeDetails(includeDetails) + var query = from apiResource in (await GetDbSetAsync()).IncludeDetails(includeDetails) where apiResource.Name == apiResourceName orderby apiResource.Id select apiResource; @@ -31,7 +31,7 @@ namespace Volo.Abp.IdentityServer.ApiResources public async Task> FindByNameAsync(string[] apiResourceNames, bool includeDetails = true, CancellationToken cancellationToken = default) { - var query = from apiResource in DbSet.IncludeDetails(includeDetails) + var query = from apiResource in (await GetDbSetAsync()).IncludeDetails(includeDetails) where apiResourceNames.Contains(apiResource.Name) orderby apiResource.Name select apiResource; @@ -44,7 +44,7 @@ namespace Volo.Abp.IdentityServer.ApiResources bool includeDetails = false, CancellationToken cancellationToken = default) { - var query = from api in DbSet.IncludeDetails(includeDetails) + var query = from api in (await GetDbSetAsync()).IncludeDetails(includeDetails) where api.Scopes.Any(x => scopeNames.Contains(x.Scope)) select api; @@ -58,7 +58,7 @@ namespace Volo.Abp.IdentityServer.ApiResources bool includeDetails = false, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || @@ -70,41 +70,49 @@ namespace Volo.Abp.IdentityServer.ApiResources public virtual async Task CheckNameExistAsync(string name, Guid? expectedId = null, CancellationToken cancellationToken = default) { - return await DbSet.AnyAsync(ar => ar.Id != expectedId && ar.Name == name, GetCancellationToken(cancellationToken)); + return await (await GetDbSetAsync()).AnyAsync(ar => ar.Id != expectedId && ar.Name == name, GetCancellationToken(cancellationToken)); } public async override Task DeleteAsync(Guid id, bool autoSave = false, CancellationToken cancellationToken = default) { - var resourceClaims = DbContext.Set().Where(sc => sc.ApiResourceId == id); + var dbContext = await GetDbContextAsync(); + + var resourceClaims = dbContext.Set().Where(sc => sc.ApiResourceId == id); foreach (var scopeClaim in resourceClaims) { - DbContext.Set().Remove(scopeClaim); + dbContext.Set().Remove(scopeClaim); } - var resourceScopes = DbContext.Set().Where(s => s.ApiResourceId == id); + var resourceScopes = dbContext.Set().Where(s => s.ApiResourceId == id); foreach (var scope in resourceScopes) { - DbContext.Set().Remove(scope); + dbContext.Set().Remove(scope); } - var resourceSecrets = DbContext.Set().Where(s => s.ApiResourceId == id); + var resourceSecrets = dbContext.Set().Where(s => s.ApiResourceId == id); foreach (var secret in resourceSecrets) { - DbContext.Set().Remove(secret); + dbContext.Set().Remove(secret); } - var apiResourceProperties = DbContext.Set().Where(s => s.ApiResourceId == id); + var apiResourceProperties = dbContext.Set().Where(s => s.ApiResourceId == id); foreach (var property in apiResourceProperties) { - DbContext.Set().Remove(property); + dbContext.Set().Remove(property); } await base.DeleteAsync(id, autoSave, cancellationToken); } + [Obsolete("Use WithDetailsAsync method.")] public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); } + + public override async Task> WithDetailsAsync() + { + return (await GetQueryableAsync()).IncludeDetails(); + } } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/ApiScopes/ApiScopeRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/ApiScopes/ApiScopeRepository.cs index c2a962ead6..4cece3209e 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/ApiScopes/ApiScopeRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/ApiScopes/ApiScopeRepository.cs @@ -20,7 +20,7 @@ namespace Volo.Abp.IdentityServer.ApiScopes public async Task GetByNameAsync(string scopeName, bool includeDetails = true, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .OrderBy(x=>x.Id) .FirstOrDefaultAsync(x => x.Name == scopeName, GetCancellationToken(cancellationToken)); } @@ -28,7 +28,7 @@ namespace Volo.Abp.IdentityServer.ApiScopes public async Task> GetListByNameAsync(string[] scopeNames, bool includeDetails = false, CancellationToken cancellationToken = default) { - var query = from scope in DbSet.IncludeDetails(includeDetails) + var query = from scope in (await GetDbSetAsync()).IncludeDetails(includeDetails) where scopeNames.Contains(scope.Name) orderby scope.Id select scope; @@ -38,7 +38,7 @@ namespace Volo.Abp.IdentityServer.ApiScopes public async Task> GetListAsync(string sorting, int skipCount, int maxResultCount, string filter = null, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || @@ -50,29 +50,36 @@ namespace Volo.Abp.IdentityServer.ApiScopes public async Task CheckNameExistAsync(string name, Guid? expectedId = null, CancellationToken cancellationToken = default) { - return await DbSet.AnyAsync(x => x.Id != expectedId && x.Name == name, GetCancellationToken(cancellationToken)); + return await (await GetDbSetAsync()).AnyAsync(x => x.Id != expectedId && x.Name == name, GetCancellationToken(cancellationToken)); } - public async override Task DeleteAsync(Guid id, bool autoSave = false, CancellationToken cancellationToken = new CancellationToken()) + public override async Task DeleteAsync(Guid id, bool autoSave = false, CancellationToken cancellationToken = new CancellationToken()) { - var scopeClaims = DbContext.Set().Where(sc => sc.ApiScopeId == id); + var dbContext = await GetDbContextAsync(); + var scopeClaims = dbContext.Set().Where(sc => sc.ApiScopeId == id); foreach (var claim in scopeClaims) { - DbContext.Set().Remove(claim); + dbContext.Set().Remove(claim); } - var scopeProperties = DbContext.Set().Where(s => s.ApiScopeId == id); + var scopeProperties = dbContext.Set().Where(s => s.ApiScopeId == id); foreach (var property in scopeProperties) { - DbContext.Set().Remove(property); + dbContext.Set().Remove(property); } await base.DeleteAsync(id, autoSave, cancellationToken); } + [Obsolete("Use WithDetailsAsync method.")] public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); } + + public override async Task> WithDetailsAsync() + { + return (await GetQueryableAsync()).IncludeDetails(); + } } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Clients/ClientRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Clients/ClientRepository.cs index 671d98d822..7607a189ca 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Clients/ClientRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Clients/ClientRepository.cs @@ -23,7 +23,7 @@ namespace Volo.Abp.IdentityServer.Clients bool includeDetails = true, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .OrderBy(x => x.ClientId) .FirstOrDefaultAsync(x => x.ClientId == clientId, GetCancellationToken(cancellationToken)); @@ -33,7 +33,7 @@ namespace Volo.Abp.IdentityServer.Clients string sorting, int skipCount, int maxResultCount, string filter, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.ClientId.Contains(filter)) .OrderBy(sorting ?? nameof(Client.ClientName) + " desc") @@ -43,7 +43,7 @@ namespace Volo.Abp.IdentityServer.Clients public virtual async Task> GetAllDistinctAllowedCorsOriginsAsync(CancellationToken cancellationToken = default) { - return await DbContext.ClientCorsOrigins + return await (await GetDbContextAsync()).ClientCorsOrigins .Select(x => x.Origin) .Distinct() .ToListAsync(GetCancellationToken(cancellationToken)); @@ -51,62 +51,70 @@ namespace Volo.Abp.IdentityServer.Clients public virtual async Task CheckClientIdExistAsync(string clientId, Guid? expectedId = null, CancellationToken cancellationToken = default) { - return await DbSet.AnyAsync(c => c.Id != expectedId && c.ClientId == clientId, cancellationToken: cancellationToken); + return await (await GetDbSetAsync()).AnyAsync(c => c.Id != expectedId && c.ClientId == clientId, cancellationToken: cancellationToken); } public async override Task DeleteAsync(Guid id, bool autoSave = false, CancellationToken cancellationToken = default) { - foreach (var clientGrantType in DbContext.Set().Where(x => x.ClientId == id)) + var dbContext = await GetDbContextAsync(); + + foreach (var clientGrantType in dbContext.Set().Where(x => x.ClientId == id)) { - DbContext.Set().Remove(clientGrantType); + dbContext.Set().Remove(clientGrantType); } - foreach (var clientRedirectUri in DbContext.Set().Where(x => x.ClientId == id)) + foreach (var clientRedirectUri in dbContext.Set().Where(x => x.ClientId == id)) { - DbContext.Set().Remove(clientRedirectUri); + dbContext.Set().Remove(clientRedirectUri); } - foreach (var clientPostLogoutRedirectUri in DbContext.Set().Where(x => x.ClientId == id)) + foreach (var clientPostLogoutRedirectUri in dbContext.Set().Where(x => x.ClientId == id)) { - DbContext.Set().Remove(clientPostLogoutRedirectUri); + dbContext.Set().Remove(clientPostLogoutRedirectUri); } - foreach (var clientScope in DbContext.Set().Where(x => x.ClientId == id)) + foreach (var clientScope in dbContext.Set().Where(x => x.ClientId == id)) { - DbContext.Set().Remove(clientScope); + dbContext.Set().Remove(clientScope); } - foreach (var clientSecret in DbContext.Set().Where(x => x.ClientId == id)) + foreach (var clientSecret in dbContext.Set().Where(x => x.ClientId == id)) { - DbContext.Set().Remove(clientSecret); + dbContext.Set().Remove(clientSecret); } - foreach (var clientClaim in DbContext.Set().Where(x => x.ClientId == id)) + foreach (var clientClaim in dbContext.Set().Where(x => x.ClientId == id)) { - DbContext.Set().Remove(clientClaim); + dbContext.Set().Remove(clientClaim); } - foreach (var clientIdPRestriction in DbContext.Set().Where(x => x.ClientId == id)) + foreach (var clientIdPRestriction in dbContext.Set().Where(x => x.ClientId == id)) { - DbContext.Set().Remove(clientIdPRestriction); + dbContext.Set().Remove(clientIdPRestriction); } - foreach (var clientCorsOrigin in DbContext.Set().Where(x => x.ClientId == id)) + foreach (var clientCorsOrigin in dbContext.Set().Where(x => x.ClientId == id)) { - DbContext.Set().Remove(clientCorsOrigin); + dbContext.Set().Remove(clientCorsOrigin); } - foreach (var clientProperty in DbContext.Set().Where(x => x.ClientId == id)) + foreach (var clientProperty in dbContext.Set().Where(x => x.ClientId == id)) { - DbContext.Set().Remove(clientProperty); + dbContext.Set().Remove(clientProperty); } await base.DeleteAsync(id, autoSave, cancellationToken); } + [Obsolete("Use WithDetailsAsync method.")] public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); } + + public override async Task> WithDetailsAsync() + { + return (await GetQueryableAsync()).IncludeDetails(); + } } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Devices/DeviceFlowCodesRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Devices/DeviceFlowCodesRepository.cs index 819c90d402..a6fd6e196b 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Devices/DeviceFlowCodesRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Devices/DeviceFlowCodesRepository.cs @@ -23,7 +23,7 @@ namespace Volo.Abp.IdentityServer.Devices string userCode, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .Where(d => d.UserCode == userCode) .OrderBy(d => d.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -33,7 +33,7 @@ namespace Volo.Abp.IdentityServer.Devices string deviceCode, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .Where(d => d.DeviceCode == deviceCode) .OrderBy(d => d.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -42,7 +42,7 @@ namespace Volo.Abp.IdentityServer.Devices public virtual async Task> GetListByExpirationAsync(DateTime maxExpirationDate, int maxResultCount, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .Where(x => x.Expiration != null && x.Expiration < maxExpirationDate) .OrderBy(x => x.ClientId) .Take(maxResultCount) diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Grants/PersistedGrantRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Grants/PersistedGrantRepository.cs index aa7a27804f..2dbdfc1a3b 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Grants/PersistedGrantRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Grants/PersistedGrantRepository.cs @@ -21,7 +21,7 @@ namespace Volo.Abp.IdentityServer.Grants public async Task> GetListAsync(string subjectId, string sessionId, string clientId, string type, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await Filter(subjectId, sessionId, clientId, type) + return await (await FilterAsync(subjectId, sessionId, clientId, type)) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -29,7 +29,7 @@ namespace Volo.Abp.IdentityServer.Grants string key, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .Where(x => x.Key == key) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -39,7 +39,7 @@ namespace Volo.Abp.IdentityServer.Grants string subjectId, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .Where(x => x.SubjectId == subjectId) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -49,7 +49,7 @@ namespace Volo.Abp.IdentityServer.Grants int maxResultCount, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .Where(x => x.Expiration != null && x.Expiration < maxExpirationDate) .OrderBy(x => x.ClientId) .Take(maxResultCount) @@ -63,21 +63,23 @@ namespace Volo.Abp.IdentityServer.Grants string type = null, CancellationToken cancellationToken = default) { - var persistedGrants = await Filter(subjectId, sessionId, clientId, type).ToListAsync(GetCancellationToken(cancellationToken)); + var persistedGrants = await (await FilterAsync(subjectId, sessionId, clientId, type)).ToListAsync(GetCancellationToken(cancellationToken)); + + var dbSet = await GetDbSetAsync(); foreach (var persistedGrant in persistedGrants) { - DbSet.Remove(persistedGrant); + dbSet.Remove(persistedGrant); } } - private IQueryable Filter( + private async Task> FilterAsync( string subjectId, string sessionId, string clientId, string type) { - return DbSet + return (await GetDbSetAsync()) .WhereIf(!subjectId.IsNullOrWhiteSpace(), x => x.SubjectId == subjectId) .WhereIf(!sessionId.IsNullOrWhiteSpace(), x => x.SessionId == sessionId) .WhereIf(!clientId.IsNullOrWhiteSpace(), x => x.ClientId == clientId) diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceRepository.cs index 6ddf38e2db..1b83b46158 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceRepository.cs @@ -24,22 +24,28 @@ namespace Volo.Abp.IdentityServer.IdentityResources bool includeDetails = false, CancellationToken cancellationToken = default) { - var query = from identityResource in DbSet.IncludeDetails(includeDetails) + var query = from identityResource in (await GetDbSetAsync()).IncludeDetails(includeDetails) where scopeNames.Contains(identityResource.Name) select identityResource; return await query.ToListAsync(GetCancellationToken(cancellationToken)); } + [Obsolete("Use WithDetailsAsync method.")] public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); } + public override async Task> WithDetailsAsync() + { + return (await GetQueryableAsync()).IncludeDetails(); + } + public virtual async Task> GetListAsync(string sorting, int skipCount, int maxResultCount, string filter, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || @@ -54,7 +60,7 @@ namespace Volo.Abp.IdentityServer.IdentityResources bool includeDetails = true, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .Where(x => x.Name == name) .OrderBy(x => x.Id) @@ -63,7 +69,7 @@ namespace Volo.Abp.IdentityServer.IdentityResources public virtual async Task CheckNameExistAsync(string name, Guid? expectedId = null, CancellationToken cancellationToken = default) { - return await DbSet.AnyAsync(ir => ir.Id != expectedId && ir.Name == name, cancellationToken: cancellationToken); + return await (await GetDbSetAsync()).AnyAsync(ir => ir.Id != expectedId && ir.Name == name, cancellationToken: cancellationToken); } } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiResourceRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiResourceRepository.cs index 599fa913b5..7db1bba8da 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiResourceRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiResourceRepository.cs @@ -6,7 +6,6 @@ using System.Threading.Tasks; using MongoDB.Driver; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; -using Volo.Abp.IdentityServer.ApiScopes; using System.Linq.Dynamic.Core; using Volo.Abp.IdentityServer.ApiResources; using Volo.Abp.MongoDB; @@ -21,7 +20,7 @@ namespace Volo.Abp.IdentityServer.MongoDB public async Task FindByNameAsync(string apiResourceName, bool includeDetails = true, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(ar => ar.Name == apiResourceName) .OrderBy(ar => ar.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -30,7 +29,7 @@ namespace Volo.Abp.IdentityServer.MongoDB public async Task> FindByNameAsync(string[] apiResourceNames, bool includeDetails = true, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(ar => apiResourceNames.Contains(ar.Name)) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -38,7 +37,7 @@ namespace Volo.Abp.IdentityServer.MongoDB public virtual async Task> GetListByScopesAsync(string[] scopeNames, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(ar => ar.Scopes.Any(x => scopeNames.Contains(x.Scope))) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -46,7 +45,7 @@ namespace Volo.Abp.IdentityServer.MongoDB public virtual async Task> GetListAsync(string sorting, int skipCount, int maxResultCount, string filter, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || @@ -57,14 +56,10 @@ namespace Volo.Abp.IdentityServer.MongoDB .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task GetTotalCount() - { - return await GetCountAsync(); - } - public virtual async Task CheckNameExistAsync(string name, Guid? expectedId = null, CancellationToken cancellationToken = default) { - return await GetMongoQueryable().AnyAsync(ar => ar.Id != expectedId && ar.Name == name, GetCancellationToken(cancellationToken)); + return await (await GetMongoQueryableAsync(cancellationToken)) + .AnyAsync(ar => ar.Id != expectedId && ar.Name == name, GetCancellationToken(cancellationToken)); } } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiScopeRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiScopeRepository.cs index 91a408392f..69faed9dc3 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiScopeRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiScopeRepository.cs @@ -22,7 +22,7 @@ namespace Volo.Abp.IdentityServer.MongoDB public async Task GetByNameAsync(string scopeName, bool includeDetails = true, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(x => x.Name == scopeName) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -31,7 +31,7 @@ namespace Volo.Abp.IdentityServer.MongoDB public async Task> GetListByNameAsync(string[] scopeNames, bool includeDetails = false, CancellationToken cancellationToken = default) { - var query = from scope in GetMongoQueryable() + var query = from scope in (await GetMongoQueryableAsync(cancellationToken)) where scopeNames.Contains(scope.Name) orderby scope.Id select scope; @@ -42,7 +42,7 @@ namespace Volo.Abp.IdentityServer.MongoDB public async Task> GetListAsync(string sorting, int skipCount, int maxResultCount, string filter = null, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || @@ -55,7 +55,8 @@ namespace Volo.Abp.IdentityServer.MongoDB public async Task CheckNameExistAsync(string name, Guid? expectedId = null, CancellationToken cancellationToken = default) { - return await GetMongoQueryable().AnyAsync(x => x.Id != expectedId && x.Name == name, GetCancellationToken(cancellationToken)); + return await (await GetMongoQueryableAsync(cancellationToken)) + .AnyAsync(x => x.Id != expectedId && x.Name == name, GetCancellationToken(cancellationToken)); } } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoClientRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoClientRepository.cs index a68f5738d0..bd99461997 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoClientRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoClientRepository.cs @@ -26,7 +26,7 @@ namespace Volo.Abp.IdentityServer.MongoDB bool includeDetails = true, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(x => x.ClientId == clientId) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -40,7 +40,7 @@ namespace Volo.Abp.IdentityServer.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), x=>x.ClientId.Contains(filter)) .OrderBy(sorting ?? nameof(Client.ClientName)) .As>() @@ -51,7 +51,7 @@ namespace Volo.Abp.IdentityServer.MongoDB public virtual async Task> GetAllDistinctAllowedCorsOriginsAsync( CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .SelectMany(x => x.AllowedCorsOrigins) .Select(y => y.Origin) .Distinct() @@ -60,12 +60,8 @@ namespace Volo.Abp.IdentityServer.MongoDB public virtual async Task CheckClientIdExistAsync(string clientId, Guid? expectedId = null, CancellationToken cancellationToken = default) { - return await GetMongoQueryable().AnyAsync(c => c.Id != expectedId && c.ClientId == clientId, cancellationToken: cancellationToken); - } - - public virtual async Task GetTotalCount() - { - return await GetCountAsync(); + return await (await GetMongoQueryableAsync(cancellationToken)) + .AnyAsync(c => c.Id != expectedId && c.ClientId == clientId, cancellationToken: cancellationToken); } } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoDeviceFlowCodesRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoDeviceFlowCodesRepository.cs index fc6dc0100a..83e87c0a58 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoDeviceFlowCodesRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoDeviceFlowCodesRepository.cs @@ -23,7 +23,7 @@ namespace Volo.Abp.IdentityServer.MongoDB string userCode, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(d => d.UserCode == userCode) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -31,7 +31,7 @@ namespace Volo.Abp.IdentityServer.MongoDB public virtual async Task FindByDeviceCodeAsync(string deviceCode, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(d => d.DeviceCode == deviceCode) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -42,7 +42,7 @@ namespace Volo.Abp.IdentityServer.MongoDB int maxResultCount, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(x => x.Expiration != null && x.Expiration < maxExpirationDate) .OrderBy(x => x.ClientId) .Take(maxResultCount) diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoIdentityResourceRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoIdentityResourceRepository.cs index 15fdf5b00c..84cc5cca0f 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoIdentityResourceRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoIdentityResourceRepository.cs @@ -20,7 +20,7 @@ namespace Volo.Abp.IdentityServer.MongoDB public virtual async Task> GetListAsync(string sorting, int skipCount, int maxResultCount, string filter, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || x.DisplayName.Contains(filter)) @@ -35,7 +35,7 @@ namespace Volo.Abp.IdentityServer.MongoDB bool includeDetails = true, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(x => x.Name == name) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -44,19 +44,15 @@ namespace Volo.Abp.IdentityServer.MongoDB public virtual async Task> GetListByScopeNameAsync(string[] scopeNames, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(ar => scopeNames.Contains(ar.Name)) .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task GetTotalCountAsync() - { - return await GetCountAsync(); - } - public virtual async Task CheckNameExistAsync(string name, Guid? expectedId = null, CancellationToken cancellationToken = default) { - return await GetMongoQueryable().AnyAsync(ir => ir.Id != expectedId && ir.Name == name, cancellationToken: cancellationToken); + return await (await GetMongoQueryableAsync(cancellationToken)) + .AnyAsync(ir => ir.Id != expectedId && ir.Name == name, cancellationToken: cancellationToken); } } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistedGrantRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistedGrantRepository.cs index 6265bcd019..2d4728a7e1 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistedGrantRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistedGrantRepository.cs @@ -21,13 +21,13 @@ namespace Volo.Abp.IdentityServer.MongoDB public async Task> GetListAsync(string subjectId, string sessionId, string clientId, string type, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await Filter(subjectId, sessionId, clientId, type) + return await (await FilterAsync(subjectId, sessionId, clientId, type)) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task FindByKeyAsync(string key, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(x => x.Key == key) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -35,7 +35,7 @@ namespace Volo.Abp.IdentityServer.MongoDB public virtual async Task> GetListBySubjectIdAsync(string subjectId, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(x => x.SubjectId == subjectId) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -43,7 +43,7 @@ namespace Volo.Abp.IdentityServer.MongoDB public virtual async Task> GetListByExpirationAsync(DateTime maxExpirationDate, int maxResultCount, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(x => x.Expiration != null && x.Expiration < maxExpirationDate) .OrderBy(x => x.ClientId) .Take(maxResultCount) @@ -57,7 +57,7 @@ namespace Volo.Abp.IdentityServer.MongoDB string type = null, CancellationToken cancellationToken = default) { - var persistedGrants = await Filter(subjectId, sessionId, clientId, type) + var persistedGrants = await (await FilterAsync(subjectId, sessionId, clientId, type)) .ToListAsync(GetCancellationToken(cancellationToken)); foreach (var persistedGrant in persistedGrants) @@ -82,13 +82,13 @@ namespace Volo.Abp.IdentityServer.MongoDB ); } - private IMongoQueryable Filter( + private async Task> FilterAsync( string subjectId, string sessionId, string clientId, string type) { - return GetMongoQueryable() + return (await GetMongoQueryableAsync()) .WhereIf>(!subjectId.IsNullOrWhiteSpace(), x => x.SubjectId == subjectId) .WhereIf>(!sessionId.IsNullOrWhiteSpace(), x => x.SessionId == sessionId) .WhereIf>(!clientId.IsNullOrWhiteSpace(), x => x.ClientId == clientId) diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/IPermissionManager.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/IPermissionManager.cs index 26310a12fe..70bb83a7d0 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/IPermissionManager.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/IPermissionManager.cs @@ -15,5 +15,7 @@ namespace Volo.Abp.PermissionManagement Task SetAsync(string permissionName, string providerName, string providerKey, bool isGranted); Task UpdateProviderKeyAsync(PermissionGrant permissionGrant, string providerKey); + + Task DeleteAsync(string providerName, string providerKey); } -} \ No newline at end of file +} diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionManager.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionManager.cs index 9a2a89e340..fc8da0c6c5 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionManager.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionManager.cs @@ -111,6 +111,16 @@ namespace Volo.Abp.PermissionManagement return await PermissionGrantRepository.UpdateAsync(permissionGrant); } + public virtual async Task DeleteAsync(string providerName, string providerKey) + { + var permissionGrants = await PermissionGrantRepository.GetListAsync(providerName, providerKey); + //TODO: Use DeleteManyAsync method + foreach (var permissionGrant in permissionGrants) + { + await PermissionGrantRepository.DeleteAsync(permissionGrant); + } + } + protected virtual async Task GetInternalAsync(PermissionDefinition permission, string providerName, string providerKey) { var result = new PermissionWithGrantedProviders(permission.Name, false); @@ -143,4 +153,4 @@ namespace Volo.Abp.PermissionManagement return result; } } -} \ No newline at end of file +} diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.EntityFrameworkCore/Volo/Abp/PermissionManagement/EntityFrameworkCore/EfCorePermissionGrantRepository.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.EntityFrameworkCore/Volo/Abp/PermissionManagement/EntityFrameworkCore/EfCorePermissionGrantRepository.cs index 5a479c348b..bc0ea04cf2 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.EntityFrameworkCore/Volo/Abp/PermissionManagement/EntityFrameworkCore/EfCorePermissionGrantRepository.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.EntityFrameworkCore/Volo/Abp/PermissionManagement/EntityFrameworkCore/EfCorePermissionGrantRepository.cs @@ -24,7 +24,7 @@ namespace Volo.Abp.PermissionManagement.EntityFrameworkCore string providerKey, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .OrderBy(x => x.Id) .FirstOrDefaultAsync(s => s.Name == name && @@ -39,7 +39,7 @@ namespace Volo.Abp.PermissionManagement.EntityFrameworkCore string providerKey, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .Where(s => s.ProviderName == providerName && s.ProviderKey == providerKey @@ -49,7 +49,7 @@ namespace Volo.Abp.PermissionManagement.EntityFrameworkCore public virtual async Task> GetListAsync(string[] names, string providerName, string providerKey, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .Where(s => names.Contains(s.Name) && s.ProviderName == providerName && diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionGrantRepository.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionGrantRepository.cs index a8f95ee6b9..823d5e63a3 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionGrantRepository.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionGrantRepository.cs @@ -24,13 +24,14 @@ namespace Volo.Abp.PermissionManagement.MongoDB string providerKey, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + cancellationToken = GetCancellationToken(cancellationToken); + return await (await GetMongoQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey, - GetCancellationToken(cancellationToken) + cancellationToken ); } @@ -39,22 +40,24 @@ namespace Volo.Abp.PermissionManagement.MongoDB string providerKey, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + cancellationToken = GetCancellationToken(cancellationToken); + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(s => s.ProviderName == providerName && s.ProviderKey == providerKey - ).ToListAsync(GetCancellationToken(cancellationToken)); + ).ToListAsync(cancellationToken); } public virtual async Task> GetListAsync(string[] names, string providerName, string providerKey, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + cancellationToken = GetCancellationToken(cancellationToken); + return await (await GetMongoQueryableAsync(cancellationToken)) .Where(s => names.Contains(s.Name) && s.ProviderName == providerName && s.ProviderKey == providerKey - ).ToListAsync(GetCancellationToken(cancellationToken)); + ).ToListAsync(cancellationToken); } } } diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/EfCoreSettingRepository.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/EfCoreSettingRepository.cs index c3323f331e..e90d2fc63a 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/EfCoreSettingRepository.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/EfCoreSettingRepository.cs @@ -17,7 +17,7 @@ namespace Volo.Abp.SettingManagement.EntityFrameworkCore public virtual async Task FindAsync(string name, string providerName, string providerKey) { - return await DbSet + return await (await GetDbSetAsync()) .OrderBy(x => x.Id) .FirstOrDefaultAsync( s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey @@ -26,7 +26,7 @@ namespace Volo.Abp.SettingManagement.EntityFrameworkCore public virtual async Task> GetListAsync(string providerName, string providerKey) { - return await DbSet + return await (await GetDbSetAsync()) .Where( s => s.ProviderName == providerName && s.ProviderKey == providerKey ).ToListAsync(); @@ -34,7 +34,7 @@ namespace Volo.Abp.SettingManagement.EntityFrameworkCore public virtual async Task> GetListAsync(string[] names, string providerName, string providerKey) { - return await DbSet + return await (await GetDbSetAsync()) .Where( s => names.Contains(s.Name) && s.ProviderName == providerName && s.ProviderKey == providerKey ).ToListAsync(); diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs index 1acaf50d56..e81e76dfcc 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs @@ -19,17 +19,23 @@ namespace Volo.Abp.SettingManagement.MongoDB public virtual async Task FindAsync(string name, string providerName, string providerKey) { - return await GetMongoQueryable().OrderBy(x => x.Id).FirstOrDefaultAsync(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey); + return await (await GetMongoQueryableAsync()) + .OrderBy(x => x.Id) + .FirstOrDefaultAsync(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey); } public virtual async Task> GetListAsync(string providerName, string providerKey) { - return await GetMongoQueryable().Where(s => s.ProviderName == providerName && s.ProviderKey == providerKey).ToListAsync(); + return await (await GetMongoQueryableAsync()) + .Where(s => s.ProviderName == providerName && s.ProviderKey == providerKey) + .ToListAsync(); } public virtual async Task> GetListAsync(string[] names, string providerName, string providerKey) { - return await GetMongoQueryable().Where(s => names.Contains(s.Name) && s.ProviderName == providerName && s.ProviderKey == providerKey).ToListAsync(); + return await (await GetMongoQueryableAsync()) + .Where(s => names.Contains(s.Name) && s.ProviderName == providerName && s.ProviderKey == providerKey) + .ToListAsync(); } } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantRepository.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantRepository.cs index 1feca866a2..8a3fc0b19a 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantRepository.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantRepository.cs @@ -9,30 +9,32 @@ namespace Volo.Abp.TenantManagement public interface ITenantRepository : IBasicRepository { Task FindByNameAsync( - string name, - bool includeDetails = true, + string name, + bool includeDetails = true, CancellationToken cancellationToken = default); + [Obsolete("Use FindByNameAsync method.")] Tenant FindByName( string name, bool includeDetails = true ); + [Obsolete("Use FindAsync method.")] Tenant FindById( Guid id, bool includeDetails = true ); Task> GetListAsync( - string sorting = null, - int maxResultCount = int.MaxValue, - int skipCount = 0, - string filter = null, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + string filter = null, bool includeDetails = false, CancellationToken cancellationToken = default); Task GetCountAsync( - string filter = null, + string filter = null, CancellationToken cancellationToken = default); } -} \ No newline at end of file +} diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs index 5847ed7d89..00b9ef0963 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs @@ -15,7 +15,7 @@ namespace Volo.Abp.TenantManagement protected ICurrentTenant CurrentTenant { get; } public TenantStore( - ITenantRepository tenantRepository, + ITenantRepository tenantRepository, IObjectMapper objectMapper, ICurrentTenant currentTenant) { @@ -52,6 +52,7 @@ namespace Volo.Abp.TenantManagement } } + [Obsolete("Use FindAsync method.")] public virtual TenantConfiguration Find(string name) { using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities! @@ -66,6 +67,7 @@ namespace Volo.Abp.TenantManagement } } + [Obsolete("Use FindAsync method.")] public virtual TenantConfiguration Find(Guid id) { using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities! diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs index be11861574..4b6208e232 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs @@ -23,11 +23,12 @@ namespace Volo.Abp.TenantManagement.EntityFrameworkCore bool includeDetails = true, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .FirstOrDefaultAsync(t => t.Name == name, GetCancellationToken(cancellationToken)); } + [Obsolete("Use FindByNameAsync method.")] public virtual Tenant FindByName(string name, bool includeDetails = true) { return DbSet @@ -35,6 +36,7 @@ namespace Volo.Abp.TenantManagement.EntityFrameworkCore .FirstOrDefault(t => t.Name == name); } + [Obsolete("Use FindAsync method.")] public virtual Tenant FindById(Guid id, bool includeDetails = true) { return DbSet @@ -50,7 +52,7 @@ namespace Volo.Abp.TenantManagement.EntityFrameworkCore bool includeDetails = false, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .WhereIf( !filter.IsNullOrWhiteSpace(), @@ -72,9 +74,15 @@ namespace Volo.Abp.TenantManagement.EntityFrameworkCore ).CountAsync(cancellationToken: cancellationToken); } + [Obsolete("Use WithDetailsAsync method.")] public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); } + + public override async Task> WithDetailsAsync() + { + return (await GetQueryableAsync()).IncludeDetails(); + } } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs index a074cd973a..a2805f7333 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs @@ -13,27 +13,29 @@ namespace Volo.Abp.TenantManagement.MongoDB { public class MongoTenantRepository : MongoDbRepository, ITenantRepository { - public MongoTenantRepository(IMongoDbContextProvider dbContextProvider) + public MongoTenantRepository(IMongoDbContextProvider dbContextProvider) : base(dbContextProvider) { } public virtual async Task FindByNameAsync( - string name, - bool includeDetails = true, + string name, + bool includeDetails = true, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .FirstOrDefaultAsync(t => t.Name == name, GetCancellationToken(cancellationToken)); } + [Obsolete("Use FindByNameAsync method.")] public virtual Tenant FindByName(string name, bool includeDetails = true) { return GetMongoQueryable() .FirstOrDefault(t => t.Name == name); } + [Obsolete("Use FindAsync method.")] public virtual Tenant FindById(Guid id, bool includeDetails = true) { return GetMongoQueryable() @@ -41,14 +43,14 @@ namespace Volo.Abp.TenantManagement.MongoDB } public virtual async Task> GetListAsync( - string sorting = null, - int maxResultCount = int.MaxValue, - int skipCount = 0, - string filter = null, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + string filter = null, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .WhereIf>( !filter.IsNullOrWhiteSpace(), u => @@ -62,7 +64,7 @@ namespace Volo.Abp.TenantManagement.MongoDB public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + return await (await GetMongoQueryableAsync(cancellationToken)) .WhereIf>( !filter.IsNullOrWhiteSpace(), u => @@ -70,4 +72,4 @@ namespace Volo.Abp.TenantManagement.MongoDB ).CountAsync(cancellationToken: cancellationToken); } } -} \ No newline at end of file +} diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantConnectionString_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantConnectionString_Tests.cs index 24c27db8ae..c6c197ea70 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantConnectionString_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantConnectionString_Tests.cs @@ -10,7 +10,7 @@ namespace Volo.Abp.TenantManagement [Theory] [InlineData("aaa")] [InlineData("bbb")] - public async Task SetValue(string value) + public void SetValue(string value) { var tenantConnectionString = new TenantConnectionString(Guid.NewGuid(), "MyConnString", "MyConnString-Value"); diff --git a/modules/users/src/Volo.Abp.Users.EntityFrameworkCore/Volo/Abp/Users/EntityFrameworkCore/EfCoreAbpUserRepositoryBase.cs b/modules/users/src/Volo.Abp.Users.EntityFrameworkCore/Volo/Abp/Users/EntityFrameworkCore/EfCoreAbpUserRepositoryBase.cs index 87a8fbc507..de27a05fbd 100644 --- a/modules/users/src/Volo.Abp.Users.EntityFrameworkCore/Volo/Abp/Users/EntityFrameworkCore/EfCoreAbpUserRepositoryBase.cs +++ b/modules/users/src/Volo.Abp.Users.EntityFrameworkCore/Volo/Abp/Users/EntityFrameworkCore/EfCoreAbpUserRepositoryBase.cs @@ -27,7 +27,9 @@ namespace Volo.Abp.Users.EntityFrameworkCore public virtual async Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default) { - return await DbSet.Where(u => ids.Contains(u.Id)).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetDbSetAsync()) + .Where(u => ids.Contains(u.Id)) + .ToListAsync(GetCancellationToken(cancellationToken)); } public async Task> SearchAsync( @@ -37,7 +39,7 @@ namespace Volo.Abp.Users.EntityFrameworkCore string filter = null, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .WhereIf( !filter.IsNullOrWhiteSpace(), u => @@ -55,7 +57,7 @@ namespace Volo.Abp.Users.EntityFrameworkCore string filter = null, CancellationToken cancellationToken = default) { - return await DbSet + return await (await GetDbSetAsync()) .WhereIf( !filter.IsNullOrWhiteSpace(), u => diff --git a/modules/users/src/Volo.Abp.Users.MongoDB/Volo/Abp/Users/MongoDB/MongoUserRepositoryBase.cs b/modules/users/src/Volo.Abp.Users.MongoDB/Volo/Abp/Users/MongoDB/MongoUserRepositoryBase.cs index cf4d860def..996b6e314c 100644 --- a/modules/users/src/Volo.Abp.Users.MongoDB/Volo/Abp/Users/MongoDB/MongoUserRepositoryBase.cs +++ b/modules/users/src/Volo.Abp.Users.MongoDB/Volo/Abp/Users/MongoDB/MongoUserRepositoryBase.cs @@ -23,12 +23,18 @@ namespace Volo.Abp.Users.MongoDB public virtual async Task FindByUserNameAsync(string userName, CancellationToken cancellationToken = default) { - return await GetMongoQueryable().OrderBy(x => x.Id).FirstOrDefaultAsync(u => u.UserName == userName, GetCancellationToken(cancellationToken)); + cancellationToken = GetCancellationToken(cancellationToken); + return await (await GetMongoQueryableAsync(cancellationToken)) + .OrderBy(x => x.Id) + .FirstOrDefaultAsync(u => u.UserName == userName, cancellationToken); } public virtual async Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default) { - return await GetMongoQueryable().Where(u => ids.Contains(u.Id)).ToListAsync(GetCancellationToken(cancellationToken)); + cancellationToken = GetCancellationToken(cancellationToken); + return await (await GetMongoQueryableAsync(cancellationToken)) + .Where(u => ids.Contains(u.Id)) + .ToListAsync(cancellationToken); } public async Task> SearchAsync( @@ -38,7 +44,8 @@ namespace Volo.Abp.Users.MongoDB string filter = null, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + cancellationToken = GetCancellationToken(cancellationToken); + return await (await GetMongoQueryableAsync(cancellationToken)) .WhereIf>( !filter.IsNullOrWhiteSpace(), u => @@ -50,12 +57,13 @@ namespace Volo.Abp.Users.MongoDB .OrderBy(sorting ?? nameof(IUserData.UserName)) .As>() .PageBy>(skipCount, maxResultCount) - .ToListAsync(GetCancellationToken(cancellationToken)); + .ToListAsync(cancellationToken); } public async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await GetMongoQueryable() + cancellationToken = GetCancellationToken(cancellationToken); + return await (await GetMongoQueryableAsync(cancellationToken)) .WhereIf>( !filter.IsNullOrWhiteSpace(), u => @@ -64,7 +72,7 @@ namespace Volo.Abp.Users.MongoDB u.Name.Contains(filter) || u.Surname.Contains(filter) ) - .LongCountAsync(GetCancellationToken(cancellationToken)); + .LongCountAsync(cancellationToken); } } } diff --git a/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts b/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts index a947809623..70adcf764e 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts @@ -2,18 +2,23 @@ import { CoreModule } from '@abp/ng.core'; import { ThemeSharedModule } from '@abp/ng.theme.shared'; import { ModuleWithProviders, NgModule } from '@angular/core'; import { NgbCollapseModule, NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; -import { NgxValidateCoreModule } from '@ngx-validate/core'; +import { + NgxValidateCoreModule, + VALIDATION_ERROR_TEMPLATE, + VALIDATION_INVALID_CLASSES, + VALIDATION_TARGET_SELECTOR, +} from '@ngx-validate/core'; import { AccountLayoutComponent } from './components/account-layout/account-layout.component'; import { ApplicationLayoutComponent } from './components/application-layout/application-layout.component'; import { EmptyLayoutComponent } from './components/empty-layout/empty-layout.component'; import { LogoComponent } from './components/logo/logo.component'; +import { CurrentUserComponent } from './components/nav-items/current-user.component'; +import { LanguagesComponent } from './components/nav-items/languages.component'; import { NavItemsComponent } from './components/nav-items/nav-items.component'; import { RoutesComponent } from './components/routes/routes.component'; import { ValidationErrorComponent } from './components/validation-error/validation-error.component'; -import { CurrentUserComponent } from './components/nav-items/current-user.component'; -import { LanguagesComponent } from './components/nav-items/languages.component'; -import { BASIC_THEME_STYLES_PROVIDERS } from './providers/styles.provider'; import { BASIC_THEME_NAV_ITEM_PROVIDERS } from './providers/nav-item.provider'; +import { BASIC_THEME_STYLES_PROVIDERS } from './providers/styles.provider'; export const LAYOUTS = [ApplicationLayoutComponent, AccountLayoutComponent, EmptyLayoutComponent]; @@ -45,37 +50,32 @@ export const LAYOUTS = [ApplicationLayoutComponent, AccountLayoutComponent, Empt ], entryComponents: [...LAYOUTS, ValidationErrorComponent, CurrentUserComponent, LanguagesComponent], }) +export class BaseThemeBasicModule {} + +@NgModule({ + exports: [BaseThemeBasicModule], + imports: [BaseThemeBasicModule], +}) export class ThemeBasicModule { static forRoot(): ModuleWithProviders { return { - ngModule: RootThemeBasicModule, - providers: [BASIC_THEME_NAV_ITEM_PROVIDERS, BASIC_THEME_STYLES_PROVIDERS], + ngModule: ThemeBasicModule, + providers: [ + BASIC_THEME_NAV_ITEM_PROVIDERS, + BASIC_THEME_STYLES_PROVIDERS, + { + provide: VALIDATION_ERROR_TEMPLATE, + useValue: ValidationErrorComponent, + }, + { + provide: VALIDATION_TARGET_SELECTOR, + useValue: '.form-group', + }, + { + provide: VALIDATION_INVALID_CLASSES, + useValue: 'is-invalid', + }, + ], }; } } - -@NgModule({ - imports: [ - NgxValidateCoreModule.forRoot({ - targetSelector: '.form-group', - blueprints: { - creditCard: 'AbpValidation::ThisFieldIsNotAValidCreditCardNumber.', - email: 'AbpValidation::ThisFieldIsNotAValidEmailAddress.', - invalid: 'AbpValidation::ThisFieldIsNotValid.', - max: 'AbpValidation::ThisFieldMustBeBetween{0}And{1}[{{ min }},{{ max }}]', - maxlength: - 'AbpValidation::ThisFieldMustBeAStringOrArrayTypeWithAMaximumLengthOf{0}[{{ requiredLength }}]', - min: 'AbpValidation::ThisFieldMustBeBetween{0}And{1}[{{ min }},{{ max }}]', - minlength: - 'AbpValidation::ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}[{{ requiredLength }}]', - ngbDate: 'AbpValidation::ThisFieldIsNotValid.', - passwordMismatch: 'AbpIdentity::Volo.Abp.Identity:PasswordConfirmationFailed', - range: 'AbpValidation::ThisFieldMustBeBetween{0}And{1}[{{ min }},{{ max }}]', - required: 'AbpValidation::ThisFieldIsRequired.', - url: 'AbpValidation::ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl', - }, - errorTemplate: ValidationErrorComponent, - }), - ], -}) -export class RootThemeBasicModule {} diff --git a/npm/ng-packs/packages/theme-basic/testing/ng-package.json b/npm/ng-packs/packages/theme-basic/testing/ng-package.json new file mode 100644 index 0000000000..c539597da7 --- /dev/null +++ b/npm/ng-packs/packages/theme-basic/testing/ng-package.json @@ -0,0 +1,7 @@ +{ + "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../dist/theme-basic/testing", + "lib": { + "entryFile": "src/public-api.ts" + } +} diff --git a/npm/ng-packs/packages/theme-basic/testing/src/lib/theme-basic-testing.module.ts b/npm/ng-packs/packages/theme-basic/testing/src/lib/theme-basic-testing.module.ts new file mode 100644 index 0000000000..7df6d40231 --- /dev/null +++ b/npm/ng-packs/packages/theme-basic/testing/src/lib/theme-basic-testing.module.ts @@ -0,0 +1,32 @@ +import { + BaseThemeBasicModule, + BASIC_THEME_NAV_ITEM_PROVIDERS, + BASIC_THEME_STYLES_PROVIDERS, + ValidationErrorComponent, +} from '@abp/ng.theme.basic'; +import { ModuleWithProviders, NgModule } from '@angular/core'; +import { VALIDATION_ERROR_TEMPLATE, VALIDATION_TARGET_SELECTOR } from '@ngx-validate/core'; + +@NgModule({ + exports: [BaseThemeBasicModule], + imports: [BaseThemeBasicModule], +}) +export class ThemeBasicTestingModule { + static forRoot(): ModuleWithProviders { + return { + ngModule: ThemeBasicTestingModule, + providers: [ + BASIC_THEME_NAV_ITEM_PROVIDERS, + BASIC_THEME_STYLES_PROVIDERS, + { + provide: VALIDATION_ERROR_TEMPLATE, + useValue: ValidationErrorComponent, + }, + { + provide: VALIDATION_TARGET_SELECTOR, + useValue: '.form-group', + }, + ], + }; + } +} diff --git a/npm/ng-packs/packages/theme-basic/testing/src/public-api.ts b/npm/ng-packs/packages/theme-basic/testing/src/public-api.ts new file mode 100644 index 0000000000..24a3ac7586 --- /dev/null +++ b/npm/ng-packs/packages/theme-basic/testing/src/public-api.ts @@ -0,0 +1 @@ +export * from './lib/theme-basic-testing.module'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/sort-order-icon/sort-order-icon.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/sort-order-icon/sort-order-icon.component.ts index 7e5d62fb6a..439989ef73 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/sort-order-icon/sort-order-icon.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/sort-order-icon/sort-order-icon.component.ts @@ -1,5 +1,8 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; +/** + * @deprecated To be deleted in v5.0. Use ngx-datatale instead. + */ @Component({ selector: 'abp-sort-order-icon', templateUrl: './sort-order-icon.component.html', diff --git a/npm/ng-packs/packages/theme-shared/src/lib/constants/validation.ts b/npm/ng-packs/packages/theme-shared/src/lib/constants/validation.ts new file mode 100644 index 0000000000..463a7b01dc --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/src/lib/constants/validation.ts @@ -0,0 +1,16 @@ +export const DEFAULT_VALIDATION_BLUEPRINTS = { + creditCard: 'AbpValidation::ThisFieldIsNotAValidCreditCardNumber.', + email: 'AbpValidation::ThisFieldIsNotAValidEmailAddress.', + invalid: 'AbpValidation::ThisFieldIsNotValid.', + max: 'AbpValidation::ThisFieldMustBeBetween{0}And{1}[{{ min }},{{ max }}]', + maxlength: + 'AbpValidation::ThisFieldMustBeAStringOrArrayTypeWithAMaximumLengthOf{0}[{{ requiredLength }}]', + min: 'AbpValidation::ThisFieldMustBeBetween{0}And{1}[{{ min }},{{ max }}]', + minlength: + 'AbpValidation::ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}[{{ requiredLength }}]', + ngbDate: 'AbpValidation::ThisFieldIsNotValid.', + passwordMismatch: 'AbpIdentity::Volo.Abp.Identity:PasswordConfirmationFailed', + range: 'AbpValidation::ThisFieldMustBeBetween{0}And{1}[{{ min }},{{ max }}]', + required: 'AbpValidation::ThisFieldIsRequired.', + url: 'AbpValidation::ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl', +}; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/models/common.ts b/npm/ng-packs/packages/theme-shared/src/lib/models/common.ts index 09171179c4..64047e0db7 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/models/common.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/models/common.ts @@ -1,7 +1,9 @@ import { Type } from '@angular/core'; +import { Validation } from '@ngx-validate/core'; export interface RootParams { httpErrorConfig: HttpErrorConfig; + validation?: Partial; } export type ErrorScreenErrorCodes = 401 | 403 | 404 | 500; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts index 6775c15e5a..037faee882 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts @@ -2,7 +2,13 @@ import { CoreModule, noop } from '@abp/ng.core'; import { DatePipe } from '@angular/common'; import { APP_INITIALIZER, Injector, ModuleWithProviders, NgModule } from '@angular/core'; import { NgbDateParserFormatter, NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap'; -import { NgxValidateCoreModule } from '@ngx-validate/core'; +import { + defaultMapErrorsFn, + NgxValidateCoreModule, + VALIDATION_BLUEPRINTS, + VALIDATION_MAP_ERRORS_FN, + VALIDATION_VALIDATE_ON_SUBMIT, +} from '@ngx-validate/core'; import { NgxDatatableModule } from '@swimlane/ngx-datatable'; import { BreadcrumbComponent } from './components/breadcrumb/breadcrumb.component'; import { ButtonComponent } from './components/button/button.component'; @@ -18,6 +24,7 @@ import { TableEmptyMessageComponent } from './components/table-empty-message/tab import { TableComponent } from './components/table/table.component'; import { ToastContainerComponent } from './components/toast-container/toast-container.component'; import { ToastComponent } from './components/toast/toast.component'; +import { DEFAULT_VALIDATION_BLUEPRINTS } from './constants/validation'; import { LoadingDirective } from './directives/loading.directive'; import { NgxDatatableDefaultDirective } from './directives/ngx-datatable-default.directive'; import { NgxDatatableListDirective } from './directives/ngx-datatable-list.directive'; @@ -69,7 +76,9 @@ export class BaseThemeSharedModule {} exports: [BaseThemeSharedModule], }) export class ThemeSharedModule { - static forRoot(options = {} as RootParams): ModuleWithProviders { + static forRoot( + { httpErrorConfig, validation = {} } = {} as RootParams, + ): ModuleWithProviders { return { ngModule: ThemeSharedModule, providers: [ @@ -92,13 +101,28 @@ export class ThemeSharedModule { deps: [Injector], useFactory: initLazyStyleHandler, }, - { provide: HTTP_ERROR_CONFIG, useValue: options.httpErrorConfig }, + { provide: HTTP_ERROR_CONFIG, useValue: httpErrorConfig }, { provide: 'HTTP_ERROR_CONFIG', useFactory: httpErrorConfigFactory, deps: [HTTP_ERROR_CONFIG], }, { provide: NgbDateParserFormatter, useClass: DateParserFormatter }, + { + provide: VALIDATION_BLUEPRINTS, + useValue: { + ...DEFAULT_VALIDATION_BLUEPRINTS, + ...(validation.blueprints || {}), + }, + }, + { + provide: VALIDATION_MAP_ERRORS_FN, + useValue: validation.mapErrorsFn || defaultMapErrorsFn, + }, + { + provide: VALIDATION_VALIDATE_ON_SUBMIT, + useValue: validation.validateOnSubmit, + }, ], }; } diff --git a/npm/ng-packs/packages/theme-shared/src/public-api.ts b/npm/ng-packs/packages/theme-shared/src/public-api.ts index 7cc8e821d5..5a4f9efe95 100644 --- a/npm/ng-packs/packages/theme-shared/src/public-api.ts +++ b/npm/ng-packs/packages/theme-shared/src/public-api.ts @@ -5,6 +5,7 @@ export * from './lib/animations'; export * from './lib/components'; export { BOOTSTRAP } from './lib/constants/styles'; +export * from './lib/constants/validation'; export * from './lib/directives'; export * from './lib/enums'; export { ErrorHandler } from './lib/handlers'; diff --git a/npm/ng-packs/packages/theme-shared/testing/src/lib/models/config.ts b/npm/ng-packs/packages/theme-shared/testing/src/lib/models/config.ts new file mode 100644 index 0000000000..1b4825cf9f --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/testing/src/lib/models/config.ts @@ -0,0 +1,5 @@ +import { Validation } from '@ngx-validate/core'; + +export interface Config { + validation?: Partial; +} diff --git a/npm/ng-packs/packages/theme-shared/testing/src/lib/models/index.ts b/npm/ng-packs/packages/theme-shared/testing/src/lib/models/index.ts new file mode 100644 index 0000000000..f03c2281a9 --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/testing/src/lib/models/index.ts @@ -0,0 +1 @@ +export * from './config'; diff --git a/npm/ng-packs/packages/theme-shared/testing/src/lib/theme-shared-testing.module.ts b/npm/ng-packs/packages/theme-shared/testing/src/lib/theme-shared-testing.module.ts index 323281046a..52abb12ffe 100644 --- a/npm/ng-packs/packages/theme-shared/testing/src/lib/theme-shared-testing.module.ts +++ b/npm/ng-packs/packages/theme-shared/testing/src/lib/theme-shared-testing.module.ts @@ -1,11 +1,19 @@ import { BaseThemeSharedModule, DateParserFormatter, + DEFAULT_VALIDATION_BLUEPRINTS, THEME_SHARED_ROUTE_PROVIDERS, } from '@abp/ng.theme.shared'; import { ModuleWithProviders, NgModule } from '@angular/core'; import { RouterTestingModule } from '@angular/router/testing'; import { NgbDateParserFormatter } from '@ng-bootstrap/ng-bootstrap'; +import { + defaultMapErrorsFn, + VALIDATION_BLUEPRINTS, + VALIDATION_MAP_ERRORS_FN, + VALIDATION_VALIDATE_ON_SUBMIT, +} from '@ngx-validate/core'; +import { Config } from './models/config'; /** * ThemeSharedTestingModule is the module that will be used in tests @@ -15,12 +23,29 @@ import { NgbDateParserFormatter } from '@ng-bootstrap/ng-bootstrap'; imports: [RouterTestingModule, BaseThemeSharedModule], }) export class ThemeSharedTestingModule { - static withConfig(): ModuleWithProviders { + static withConfig( + { validation = {} } = {} as Config, + ): ModuleWithProviders { return { ngModule: ThemeSharedTestingModule, providers: [ THEME_SHARED_ROUTE_PROVIDERS, { provide: NgbDateParserFormatter, useClass: DateParserFormatter }, + { + provide: VALIDATION_BLUEPRINTS, + useValue: { + ...DEFAULT_VALIDATION_BLUEPRINTS, + ...(validation.blueprints || {}), + }, + }, + { + provide: VALIDATION_MAP_ERRORS_FN, + useValue: validation.mapErrorsFn || defaultMapErrorsFn, + }, + { + provide: VALIDATION_VALIDATE_ON_SUBMIT, + useValue: validation.validateOnSubmit, + }, ], }; } diff --git a/npm/ng-packs/packages/theme-shared/testing/src/public-api.ts b/npm/ng-packs/packages/theme-shared/testing/src/public-api.ts index 14355a8a28..dc639b1462 100644 --- a/npm/ng-packs/packages/theme-shared/testing/src/public-api.ts +++ b/npm/ng-packs/packages/theme-shared/testing/src/public-api.ts @@ -1 +1,3 @@ +import * as ThemeSharedTesting from './lib/models'; export * from './lib/theme-shared-testing.module'; +export { ThemeSharedTesting }; diff --git a/npm/ng-packs/yarn.lock b/npm/ng-packs/yarn.lock index a3f300d1c8..bc2c1e46f5 100644 --- a/npm/ng-packs/yarn.lock +++ b/npm/ng-packs/yarn.lock @@ -92,14 +92,7 @@ chart.js "^2.9.3" tslib "^2.0.0" -"@abp/utils@^4.1.0-rc.1": - version "4.1.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-4.1.0-rc.1.tgz#2863867985db9d178a5ce4347309f060f1ce6142" - integrity sha512-C8e+x5/IdkJWQ8gLtO7ygsth5sd1iXKn0ARu/5u0g11nMjHsMY9Qkwg5QrnpHp2ws1+FL1Dg67omrQp9+KK5SA== - dependencies: - just-compare "^1.3.0" - -"@abp/utils@^4.1.0-rc.2": +"@abp/utils@^4.1.0-rc.1", "@abp/utils@^4.1.0-rc.2": version "4.1.0-rc.2" resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-4.1.0-rc.2.tgz#eb6dbf0ee493d0f050b37347d2d6d283098aedae" integrity sha512-V2k5I89lVBoeGIKgg4p2H9GlMAcDWbctwKZPVwBEMVEVm1uTR2xQAWdTdSFd5Q8I8Xsf/aIG8ELM7l5j2h7/zQ== @@ -124,31 +117,31 @@ "@angular-devkit/core" "10.1.7" rxjs "6.6.2" -"@angular-devkit/architect@0.1100.4": - version "0.1100.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1100.4.tgz#68c2b0333daa0291ad99205862111c04e7a63020" - integrity sha512-hzTfcSUwM0jsSt9HvvSFyaoAhX9k73L7y4kmkghzIFhKhIKOp/7o3n7hAFwN/jWKKmVQpPKnYmqzm9H9OveaCQ== +"@angular-devkit/architect@0.1100.5": + version "0.1100.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1100.5.tgz#3cf9b25464d484160b10417668efbdbd15c9e492" + integrity sha512-yOYfucNouc1doTbcGbCNMXGMSc36+j97XpdNoeGyzFQ7GwezLAro0a9gxc5PdOxndfelkND7J1JuOjxdW5O17A== dependencies: - "@angular-devkit/core" "11.0.4" + "@angular-devkit/core" "11.0.5" rxjs "6.6.3" "@angular-devkit/architect@>=0.1000.0 < 0.1100.0": - version "0.1002.0" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1002.0.tgz#470b78aaf79308a23da6a0d3935f2d1f85dcb212" - integrity sha512-twM8V03ujBIGVpgV1PBlSDodUdxtUb7WakutfWafAvEHUsgwzfvQz2VtKWvjNZ9AiYjnCuwkQaclqVv0VHNo9w== + version "0.1002.1" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1002.1.tgz#bd33dda1361b5d7c23e07b41a603b48ac9c3c744" + integrity sha512-vP27xCe++p3zm+zwSDXDm9/rsM71Q4MYidLLi0MQfo8wxsWS/4mWXycCBoMwDkvW44SPJ4Ds1/F46bb3/xRDvA== dependencies: - "@angular-devkit/core" "10.2.0" + "@angular-devkit/core" "10.2.1" rxjs "6.6.2" "@angular-devkit/build-angular@~0.1100.0": - version "0.1100.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.1100.4.tgz#22596475d38b13735876a4c7e1afc199654bb9ed" - integrity sha512-qVkMbtOwlo+k8fvOBOwwfKWMx06k4I1qrdjpRYAoZCt3cdje4EBepSciLrHnTB+ouIqWxpEDfEXTYBS98tXbBg== - dependencies: - "@angular-devkit/architect" "0.1100.4" - "@angular-devkit/build-optimizer" "0.1100.4" - "@angular-devkit/build-webpack" "0.1100.4" - "@angular-devkit/core" "11.0.4" + version "0.1100.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.1100.5.tgz#36a609a334369d9597ac50731f458440ffdbb2d1" + integrity sha512-lJYsnBImBAqUAIVC2qGY64UaC2uWOPZEpSWjYUxkRZA/c4IVCJj3M12CgONBjtcKYzFVXc1eojhrScukGIJJcg== + dependencies: + "@angular-devkit/architect" "0.1100.5" + "@angular-devkit/build-optimizer" "0.1100.5" + "@angular-devkit/build-webpack" "0.1100.5" + "@angular-devkit/core" "11.0.5" "@babel/core" "7.12.3" "@babel/generator" "7.12.1" "@babel/plugin-transform-runtime" "7.12.1" @@ -156,7 +149,7 @@ "@babel/runtime" "7.12.1" "@babel/template" "7.10.4" "@jsdevtools/coverage-istanbul-loader" "3.0.5" - "@ngtools/webpack" "11.0.4" + "@ngtools/webpack" "11.0.5" ansi-colors "4.1.1" autoprefixer "9.8.6" babel-loader "8.1.0" @@ -223,10 +216,10 @@ "@angular-devkit/architect" "0.1001.7" rxjs "6.6.2" -"@angular-devkit/build-optimizer@0.1100.4": - version "0.1100.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.1100.4.tgz#dbe44ad1d4a6e95436e3bae297dafc09a8ab9190" - integrity sha512-C05y4qMb05PWR7l1gZwRQKiB6KIDq+p72r8Yr6jm0UO6raOtMM72R8nHnioMnGJcFtZDEAYXEF+X7soI3MMlfw== +"@angular-devkit/build-optimizer@0.1100.5": + version "0.1100.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.1100.5.tgz#25de00e9cbea1444f911aa0a7a53a05800c90d62" + integrity sha512-aKITFuiydR681eS1z84EIdOtqdxP/V5xGZuF3xjGmg5Ddwv36PweAHaCVJEB4btHSWH6uxMvW2hLXg2RTWbRNg== dependencies: loader-utils "2.0.0" source-map "0.7.3" @@ -234,13 +227,13 @@ typescript "4.0.5" webpack-sources "2.0.1" -"@angular-devkit/build-webpack@0.1100.4": - version "0.1100.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1100.4.tgz#8ca4b10ce8fc739b128137c6c7c0d24377d27a76" - integrity sha512-uxe8gNSej3KF1FgqNtJmuRDbbINh3yLtXanXhRxFQLUj8IiNR8IciIVvy6RfXC5gqxcWwy1cOefJLLnuN9AOxQ== +"@angular-devkit/build-webpack@0.1100.5": + version "0.1100.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1100.5.tgz#81be4b35dc90ea66be205ad1cb9dc44dc31bf9e0" + integrity sha512-oD5t2oCfyiCyyeZckrqBnQco94zIMkRnRGzy3lFDH7KMiL0DG9l7x3nxn9H0YunYWr55LsGWwXGoR7l03Kl+jw== dependencies: - "@angular-devkit/architect" "0.1100.4" - "@angular-devkit/core" "11.0.4" + "@angular-devkit/architect" "0.1100.5" + "@angular-devkit/core" "11.0.5" rxjs "6.6.3" "@angular-devkit/core@10.0.8": @@ -265,10 +258,10 @@ rxjs "6.6.2" source-map "0.7.3" -"@angular-devkit/core@10.2.0", "@angular-devkit/core@^10.0.0": - version "10.2.0" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-10.2.0.tgz#fcde160afc2786d2da0166526f065c6cf98684c0" - integrity sha512-XAszFhSF3mZw1VjoOsYGbArr5NJLcStjOvcCGjBPl1UBM2AKpuCQXHxI9XJGYKL3B93Vp5G58d8qkHvamT53OA== +"@angular-devkit/core@10.2.1", "@angular-devkit/core@^10.0.0": + version "10.2.1" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-10.2.1.tgz#3ae38be4ca56c745788481b3577173ac2007e9e0" + integrity sha512-dzlF9Gl7KNt9sPYT2HYq6ySZYwKzkyYR5mrBj3DZOD0OQsoc21LvLkWAHNSL2iYGdHJQS1oJDNs8iRYxYIOY3w== dependencies: ajv "6.12.4" fast-json-stable-stringify "2.1.0" @@ -276,10 +269,10 @@ rxjs "6.6.2" source-map "0.7.3" -"@angular-devkit/core@11.0.4", "@angular-devkit/core@~11.0.2": - version "11.0.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-11.0.4.tgz#4128b90bdb4d1803bb246d177b7cc6df64a0fec1" - integrity sha512-LgTvhZ3Ycz0QvNAH/zO1rpQQDn2JN8u9/Awy1gW/XeCC3FYmxeOj/2JCFzlKah3wJv16nMqro5WTppHt8Y++PA== +"@angular-devkit/core@11.0.5", "@angular-devkit/core@~11.0.2": + version "11.0.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-11.0.5.tgz#8239486d2de6c08fc55d2a64f12a7f5d518c8beb" + integrity sha512-hwV8fjF8JNPJkiVWw8MNzeIfDo01aD/OAOlC4L5rQnVHn+i2EiU3brSDmFqyeHPPV3h/QjuBkS3tkN7gSnVWaQ== dependencies: ajv "6.12.6" fast-json-stable-stringify "2.1.0" @@ -329,12 +322,12 @@ ora "5.0.0" rxjs "6.6.2" -"@angular-devkit/schematics@11.0.4", "@angular-devkit/schematics@~11.0.2": - version "11.0.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-11.0.4.tgz#0680fe038c66f2ecc3c69a293505fb02b694ce80" - integrity sha512-fFC7qW9A1bFAZgpCfkezBA4WCRzfVFgOzwPpyt65rgSrzw0+EeHjcrUIcXlhyOXAFrTHtA9oLCfEeSjSx5HBEA== +"@angular-devkit/schematics@11.0.5", "@angular-devkit/schematics@~11.0.2": + version "11.0.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-11.0.5.tgz#e5d89451daa644eccce93970709f7cdf44c11982" + integrity sha512-0NKGC8Nf/4vvDpWKB7bwxIazvNnNHnZBX6XlyBXNl+fW8tpTef3PNMJMSErTz9LFnuv61vsKbc36u/Ek2YChWg== dependencies: - "@angular-devkit/core" "11.0.4" + "@angular-devkit/core" "11.0.5" ora "5.1.0" rxjs "6.6.3" @@ -347,9 +340,9 @@ rxjs "6.4.0" "@angular/animations@~11.0.0": - version "11.0.4" - resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-11.0.4.tgz#fa669490d039455e63413a6b8cd1ff6b7a966bec" - integrity sha512-NI7UdLNdzTfLCDu0zVqwhdKq2z1flRsM2GCD9RHG/NRjlohh73uRTBW+BcYpfh+o+Wq4giiq8UkTIgS2ReqDGg== + version "11.0.5" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-11.0.5.tgz#44157c8bbb3f20ce1d3d6386eae956659cefd9d7" + integrity sha512-ghE/xDTYuEWkKNZtioH9JBrSlux0MLHzWoE7tNP+XMaplt80lCm979vWsEBO3/xpQLRmRlGPul6RacCAoeqogg== dependencies: tslib "^2.0.0" @@ -363,19 +356,19 @@ parse5 "^5.0.0" "@angular/cli@~11.0.0": - version "11.0.4" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-11.0.4.tgz#a04724f7ffb27417df59c2359e47ec54e1f61fab" - integrity sha512-VkE/gx6P80EJHg13fG+gkZfd2DJmRaDAtnamcCGM4AThzoUN9XBdxc24uMLEzBb0/mJ4vpMK9+WTNIdMmzl+Tg== - dependencies: - "@angular-devkit/architect" "0.1100.4" - "@angular-devkit/core" "11.0.4" - "@angular-devkit/schematics" "11.0.4" - "@schematics/angular" "11.0.4" - "@schematics/update" "0.1100.4" + version "11.0.5" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-11.0.5.tgz#1066d290fc91460f98cedcfbc9a5736340661467" + integrity sha512-k4j/2z7qkuigJ1shH0McW1wW63clhrbrg98FK4/KWhU/sce5AgVjuHDQFycAclTwHesf7Vs6Gzt7zGlqUmeKIg== + dependencies: + "@angular-devkit/architect" "0.1100.5" + "@angular-devkit/core" "11.0.5" + "@angular-devkit/schematics" "11.0.5" + "@schematics/angular" "11.0.5" + "@schematics/update" "0.1100.5" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.1" debug "4.2.0" - ini "1.3.5" + ini "1.3.6" inquirer "7.3.3" npm-package-arg "8.1.0" npm-pick-manifest "6.1.0" @@ -389,9 +382,9 @@ uuid "8.3.1" "@angular/common@~11.0.0": - version "11.0.4" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-11.0.4.tgz#39cd88bfcecd895419c059c366eac2df2ca6a2e9" - integrity sha512-4R2ALj71J6EAHVCKNnHHCKL7wcosMsv3gcMXbMTE+Wpzo3khEhM0Tej+I1qmMbVmGXVlRb//4+rjE4gff6FvQw== + version "11.0.5" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-11.0.5.tgz#7ec508cb7e14cf38640fe4e1c0fa3dd322a52505" + integrity sha512-aoXdTkoni65LWhrPKNsAiOnO70XFaTaisO+K8ZYMpciMTTAxHx3hFCF9sj4a+Bo3M1a5UDjpsFDYMeGgJOkmFA== dependencies: tslib "^2.0.0" @@ -434,23 +427,23 @@ integrity sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w== "@angular/core@~11.0.0": - version "11.0.4" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-11.0.4.tgz#8eebb6a550dc24e4d53f642c8a78a0da2830cd5b" - integrity sha512-860cTMjdCHcvEsHOsTzpg5rThxwVgtnY4yT0SgboWiphrlzX+aNoyN/cCJHxWhmOTRlrl6/+hkeRq95E2BZkKw== + version "11.0.5" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-11.0.5.tgz#b8c448c3cd4f6dae7327cc1ba4ee2aa29c8dbc26" + integrity sha512-XAXWQi7R3ucZXQwx9QK5jSKJeQyRJ53u2dQDpr7R5stzeCy1a5hrNOkZLg9zOTTPcth/6+FrOrRZP9SMdxtw3w== dependencies: tslib "^2.0.0" "@angular/forms@~11.0.0": - version "11.0.4" - resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-11.0.4.tgz#6d77f01ecdf027a78df18d4e6cd3ad8fc8dd49e4" - integrity sha512-Fhfc4buwMZk0WumDvl/X7XBnOKFeTRTJrwKdi8LlhY6o1Og8H4e/f69u9iDJCF3YjU4qC6yGtPp9YpSVCPP7Ew== + version "11.0.5" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-11.0.5.tgz#1be90f86b45a3d672eecea249b1d8e5e9f8f0bc3" + integrity sha512-2zB1IuqYNJrjh7Og9J8f/AtjX3NHc3VVbt0rPw35ghqIU3aQLpOichdQ1y5QvMWic1UzZ7SjWXDU7RpKbm4iUA== dependencies: tslib "^2.0.0" "@angular/language-service@~11.0.0": - version "11.0.4" - resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-11.0.4.tgz#0a9c01170be92378f217dea3263c4eb2f8411aaa" - integrity sha512-KtQxVSlZi3SwZEN4E56KHkNTFEYa3FPZfLJFm6WD1dSobFyMwJgvztO08GWSaT4S0ht0NNRD2IRt0XzBYuZkag== + version "11.0.5" + resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-11.0.5.tgz#92499b5f29509142f29ae7af64b049765a7f7050" + integrity sha512-EzGycD9ztTKAZB+kR+masNqCfGmU0vnKd/z33VLmeo9fo41t/YNCEQEEFz/pEl2dEwX/Wjou+3oyTYZIZz2uSA== "@angular/localize@~10.0.10": version "10.0.14" @@ -462,32 +455,32 @@ yargs "15.3.0" "@angular/localize@~11.0.0": - version "11.0.4" - resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-11.0.4.tgz#8f7a36685d97f26d52e3f19d9218e1e2e05a2bb2" - integrity sha512-r0dWvwFvEqQJ/H94rr548S092Hq53RqyMANuFD09CpkWXS6yAWBfArB6mW77PARnicEC0zkbi5qMGACjtSyNtA== + version "11.0.5" + resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-11.0.5.tgz#e770d4ec1b2094822fdb0524516dca6bf39dfd05" + integrity sha512-tvzgRa/t0xCouCPFMurqZImLeWIISUjVEzkcny9P7xaaz0Cw7kSyulc0e8HXf+8oijSJ624YOYUzr7mkPoIfew== dependencies: "@babel/core" "7.8.3" glob "7.1.2" yargs "^16.1.1" "@angular/platform-browser-dynamic@~11.0.0": - version "11.0.4" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-11.0.4.tgz#d775f12954db689507ef98a51d8d7ed5763becd4" - integrity sha512-ZOWTZaFfZSHhMy7a0RIxipiZoiobHWrGlq8/YaMrIgzUb9Fv518FeFCCI68BP0/GuyxX74MJmzv4ZgQctKKxXw== + version "11.0.5" + resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-11.0.5.tgz#1e1de1ca429d85eb43b14cd5da90eba4ac95bd76" + integrity sha512-MFjpQcqkHOu8iTUMKVG6vfuOHwrRlgPBvkNucEbtXhTTYNlsw2mprxfUODYEu26EBUAh+FGttu8ZjclUGw4bVg== dependencies: tslib "^2.0.0" "@angular/platform-browser@~11.0.0": - version "11.0.4" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-11.0.4.tgz#131db1115943eb9c0191080e200c1e9dbd214d4c" - integrity sha512-+uUCKJgspSghJ3R6Fk0XHA0tolbaRBi8JFS2cY+hi9s27WKB88peGvtsK6RCOPJONY6JdOuhpcZqRN8dKfPi7w== + version "11.0.5" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-11.0.5.tgz#b695d2533491f85721612a41d6d3708791bca96c" + integrity sha512-173JZHF3QS78hEscBxFZ/kX8KLjdaDhfAYi4Sh8daIKNUcDcyhqEy7wpAjWmCwdspL1QUtWKCrhZqrEVNGTpvA== dependencies: tslib "^2.0.0" "@angular/router@~11.0.0": - version "11.0.4" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-11.0.4.tgz#324507346c508649135f56e5f2b57c60e0ba7b16" - integrity sha512-B0sqv8zMM6j88+udEZzO8wKBw61pHgWZmLopnAqA65rRPrAvMsvAHUnYqX6w5pYqhJQxCVLVeKM+0QlQh1+WnA== + version "11.0.5" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-11.0.5.tgz#95d47b3b510f6a49597db64cfd7ef936bb24c402" + integrity sha512-mSD4tbzuFH4uBb9vxPQHBUbkIMoWAfVUb7r9gtn3/deOxQbVh08f2gk2iWDN3OQLAa5mNHswuLByAYSw2rPbMA== dependencies: tslib "^2.0.0" @@ -506,10 +499,10 @@ "@ant-design/colors" "^5.0.0" tslib "^2.0.0" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" - integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11", "@babel/code-frame@^7.8.3": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== dependencies: "@babel/highlight" "^7.10.4" @@ -591,12 +584,12 @@ jsesc "^2.5.1" source-map "^0.5.0" -"@babel/generator@^7.12.1", "@babel/generator@^7.12.10", "@babel/generator@^7.8.3": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.10.tgz#2b188fc329fb8e4f762181703beffc0fe6df3460" - integrity sha512-6mCdfhWgmqLdtTkhXjnIz0LcdVCd26wS2JXRtj2XY0u5klDsXBREA/pG5NVOuVnF2LUrBGNFtQkIqqTbblg0ww== +"@babel/generator@^7.12.1", "@babel/generator@^7.12.10", "@babel/generator@^7.12.11", "@babel/generator@^7.8.3": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.11.tgz#98a7df7b8c358c9a37ab07a24056853016aba3af" + integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA== dependencies: - "@babel/types" "^7.12.10" + "@babel/types" "^7.12.11" jsesc "^2.5.1" source-map "^0.5.0" @@ -660,16 +653,16 @@ dependencies: "@babel/types" "^7.12.1" -"@babel/helper-function-name@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" - integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== +"@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz#1fd7738aee5dcf53c3ecff24f1da9c511ec47b42" + integrity sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA== dependencies: - "@babel/helper-get-function-arity" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/helper-get-function-arity" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/types" "^7.12.11" -"@babel/helper-get-function-arity@^7.10.4": +"@babel/helper-get-function-arity@^7.12.10": version "7.12.10" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz#b158817a3165b5faa2047825dfa61970ddcc16cf" integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag== @@ -683,7 +676,7 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-member-expression-to-functions@^7.12.1": +"@babel/helper-member-expression-to-functions@^7.12.1", "@babel/helper-member-expression-to-functions@^7.12.7": version "7.12.7" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz#aa77bd0396ec8114e5e30787efa78599d874a855" integrity sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw== @@ -712,7 +705,7 @@ "@babel/types" "^7.12.1" lodash "^4.17.19" -"@babel/helper-optimise-call-expression@^7.10.4": +"@babel/helper-optimise-call-expression@^7.10.4", "@babel/helper-optimise-call-expression@^7.12.10": version "7.12.10" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz#94ca4e306ee11a7dd6e9f42823e2ac6b49881e2d" integrity sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ== @@ -734,14 +727,14 @@ "@babel/types" "^7.12.1" "@babel/helper-replace-supers@^7.12.1": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz#f009a17543bbbbce16b06206ae73b63d3fca68d9" - integrity sha512-5YILoed0ZyIpF4gKcpZitEnXEJ9UoDRki1Ey6xz46rxOzfNMAhVIJMoune1hmPVxh40LRv1+oafz7UsWX+vyWA== + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz#ea511658fc66c7908f923106dd88e08d1997d60d" + integrity sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA== dependencies: - "@babel/helper-member-expression-to-functions" "^7.12.1" - "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/traverse" "^7.12.5" - "@babel/types" "^7.12.5" + "@babel/helper-member-expression-to-functions" "^7.12.7" + "@babel/helper-optimise-call-expression" "^7.12.10" + "@babel/traverse" "^7.12.10" + "@babel/types" "^7.12.11" "@babel/helper-simple-access@^7.12.1": version "7.12.1" @@ -757,22 +750,22 @@ dependencies: "@babel/types" "^7.12.1" -"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" - integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== +"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz#1b4cc424458643c47d37022223da33d76ea4603a" + integrity sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g== dependencies: - "@babel/types" "^7.11.0" + "@babel/types" "^7.12.11" -"@babel/helper-validator-identifier@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" - integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== +"@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== "@babel/helper-validator-option@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz#175567380c3e77d60ff98a54bb015fe78f2178d9" - integrity sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A== + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" + integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== "@babel/helper-wrap-function@^7.10.4": version "7.12.3" @@ -802,15 +795,15 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.12.10", "@babel/parser@^7.12.3", "@babel/parser@^7.12.7", "@babel/parser@^7.8.3": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.10.tgz#824600d59e96aea26a5a2af5a9d812af05c3ae81" - integrity sha512-PJdRPwyoOqFAWfLytxrWwGrAxghCgh/yTNCYciOz8QgjflA7aZhECPZAa2VUedKg2+QMWkI0L9lynh2SNmNEgA== +"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.3", "@babel/parser@^7.12.7", "@babel/parser@^7.8.3": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79" + integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg== "@babel/plugin-proposal-async-generator-functions@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz#dc6c1170e27d8aca99ff65f4925bd06b1c90550e" - integrity sha512-d+/o30tJxFxrA1lhzJqiUcEJdI6jKlNregCv5bASeGf2Q4MXmnwH7viDo7nhx1/ohf09oaH8j1GVYG/e3Yqk6A== + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz#04b8f24fd4532008ab4e79f788468fd5a8476566" + integrity sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-remap-async-to-generator" "^7.12.1" @@ -1036,9 +1029,9 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-block-scoping@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.1.tgz#f0ee727874b42a208a48a586b84c3d222c2bbef1" - integrity sha512-zJyAC9sZdE60r1nVQHblcfCj29Dh2Y0DOvlMkcqSo0ckqjiCwNiUezUKw+RjOCwGfpLRwnAeQ2XlLpsnGkvv9w== + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz#d93a567a152c22aea3b1929bb118d1d0a175cdca" + integrity sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -1387,26 +1380,26 @@ "@babel/types" "^7.12.7" "@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5", "@babel/traverse@^7.8.3": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.10.tgz#2d1f4041e8bf42ea099e5b2dc48d6a594c00017a" - integrity sha512-6aEtf0IeRgbYWzta29lePeYSk+YAFIC3kyqESeft8o5CkFlYIMX+EQDDWEiAQ9LHOA3d0oHdgrSsID/CKqXJlg== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.10" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/parser" "^7.12.10" - "@babel/types" "^7.12.10" + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.12.tgz#d0cd87892704edd8da002d674bc811ce64743376" + integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w== + dependencies: + "@babel/code-frame" "^7.12.11" + "@babel/generator" "^7.12.11" + "@babel/helper-function-name" "^7.12.11" + "@babel/helper-split-export-declaration" "^7.12.11" + "@babel/parser" "^7.12.11" + "@babel/types" "^7.12.12" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.10.tgz#7965e4a7260b26f09c56bcfcb0498af1f6d9b260" - integrity sha512-sf6wboJV5mGyip2hIpDSKsr80RszPinEFjsHTalMxZAZkoQ2/2yQzxlcFN52SJqsyPfLtPmenL4g2KB3KJXPDw== +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299" + integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ== dependencies: - "@babel/helper-validator-identifier" "^7.10.4" + "@babel/helper-validator-identifier" "^7.12.11" lodash "^4.17.19" to-fast-properties "^2.0.0" @@ -2473,12 +2466,12 @@ jquery "3.5.0" replace-in-file "^4.1.3" -"@ngtools/webpack@11.0.4": - version "11.0.4" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-11.0.4.tgz#fd80a8b7d648ddb8e56d73404e6b673903d2d365" - integrity sha512-MAV7inQmsMISTnDcXwyRX5oJZx8F7K/tZRLJciQwkM0DqZyq8fI9KDRwBcmYeQ+J0mSJV9LUVdExmpulpkywqw== +"@ngtools/webpack@11.0.5": + version "11.0.5" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-11.0.5.tgz#9d1abb9f9a5e72c014b5ed3e0c2cefe2a4175b30" + integrity sha512-hM0LdOSlC6c7ij+BvIpAFbe7dpJhL+A51L5v6YbMA6aM0Sb/y+HpE2u34AHEQvute7cLe4EyOyvJ9jSinVAJhQ== dependencies: - "@angular-devkit/core" "11.0.4" + "@angular-devkit/core" "11.0.5" enhanced-resolve "5.3.1" webpack-sources "2.0.1" @@ -2510,18 +2503,18 @@ dependencies: tslib "^1.9.0" -"@nodelib/fs.scandir@2.1.3": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" - integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== +"@nodelib/fs.scandir@2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69" + integrity sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA== dependencies: - "@nodelib/fs.stat" "2.0.3" + "@nodelib/fs.stat" "2.0.4" run-parallel "^1.1.9" -"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" - integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== +"@nodelib/fs.stat@2.0.4", "@nodelib/fs.stat@^2.0.2": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz#a3f2dd61bab43b8db8fa108a121cfffe4c676655" + integrity sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q== "@nodelib/fs.stat@^1.1.2": version "1.1.3" @@ -2529,11 +2522,11 @@ integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== "@nodelib/fs.walk@^1.2.3": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" - integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + version "1.2.6" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz#cce9396b30aa5afe9e3756608f5831adcb53d063" + integrity sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow== dependencies: - "@nodelib/fs.scandir" "2.1.3" + "@nodelib/fs.scandir" "2.1.4" fastq "^1.6.0" "@npmcli/move-file@^1.0.1": @@ -2559,10 +2552,10 @@ is-plain-object "^5.0.0" universal-user-agent "^6.0.0" -"@octokit/openapi-types@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-2.0.0.tgz#6d8f8ad9db3b75a39115f5def2654df8bed39f28" - integrity sha512-J4bfM7lf8oZvEAdpS71oTvC1ofKxfEZgU5vKVwzZKi4QPiL82udjpseJwxPid9Pu2FNmyRQOX4iEj6W1iOSnPw== +"@octokit/openapi-types@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-2.0.1.tgz#7453d8281ce66b8ed1607f7ac7d751c3baffd2cc" + integrity sha512-9AuC04PUnZrjoLiw3uPtwGh9FE4Q3rTqs51oNlQ0rkwgE8ftYsOC+lsrQyvCvWm85smBbSc0FNRKKumvGyb44Q== "@octokit/plugin-enterprise-rest@^6.0.1": version "6.0.1" @@ -2651,11 +2644,11 @@ "@types/node" ">= 8" "@octokit/types@^6.0.0", "@octokit/types@^6.0.3": - version "6.1.1" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.1.1.tgz#bc88b3eb5f447b025a2a1a8177a72db216e8d4ca" - integrity sha512-btm3D6S7VkRrgyYF31etUtVY/eQ1KzrNRqhFt25KSe2mKlXuLXJilglRC6eDA2P6ou94BUnk/Kz5MPEolXgoiw== + version "6.1.2" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.1.2.tgz#2b3a6ae0b8b71c27c770b4ff3e9ad8f1f538af58" + integrity sha512-LPCpcLbcky7fWfHCTuc7tMiSHFpFlrThJqVdaHgowBTMS0ijlZFfonQC/C1PrZOjD4xRCYgBqH9yttEATGE/nw== dependencies: - "@octokit/openapi-types" "^2.0.0" + "@octokit/openapi-types" "^2.0.1" "@types/node" ">= 8" "@rollup/plugin-commonjs@^15.0.0": @@ -2699,13 +2692,13 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@schematics/angular@11.0.4": - version "11.0.4" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-11.0.4.tgz#36268ebda718c4f395457d2eea874fda9c469402" - integrity sha512-LwBD9TIoLy9XqqInJvlN4BHtPyJExyeorNiOp6rXb/wafuDbvZ+9kY9GWZTY1auVo5PNKqErfxr74ydA3FFb9g== +"@schematics/angular@11.0.5": + version "11.0.5" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-11.0.5.tgz#149f908fd600e881ff87c5192d2673d0e3c37f38" + integrity sha512-7p2wweoJYhim8YUy3ih1SrPGqRsa6+aEFbYgo9v4zt7b3tOva8SvkbC2alayK74fclzQ7umqa6xAwvWhy8ORvg== dependencies: - "@angular-devkit/core" "11.0.4" - "@angular-devkit/schematics" "11.0.4" + "@angular-devkit/core" "11.0.5" + "@angular-devkit/schematics" "11.0.5" jsonc-parser "2.3.1" "@schematics/angular@~10.0.5": @@ -2724,15 +2717,15 @@ "@angular-devkit/core" "10.1.7" "@angular-devkit/schematics" "10.1.7" -"@schematics/update@0.1100.4": - version "0.1100.4" - resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.1100.4.tgz#b67efdb39396ddcacef97de008100944af3d1556" - integrity sha512-YwFtgxCQQkYC89IC7dfshyGr0roE6bpp5HgpQLdS/AOjHeZKo7/SPdM0W4ddB+Fml1Fo6v4eFG/Ia9oR7qNv1A== +"@schematics/update@0.1100.5": + version "0.1100.5" + resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.1100.5.tgz#40b529d93db51e6f66378bd9f4ff99f2e9c278f6" + integrity sha512-BYtKKuiWsrlc4FMW3bRyl4tm6lWNMTi8oql/mtkSgH7V5eMmaLDJtM+zDl+qyC/KHPxbHTfoHDapfv1tITSWjA== dependencies: - "@angular-devkit/core" "11.0.4" - "@angular-devkit/schematics" "11.0.4" + "@angular-devkit/core" "11.0.5" + "@angular-devkit/schematics" "11.0.5" "@yarnpkg/lockfile" "1.1.0" - ini "1.3.5" + ini "1.3.6" npm-package-arg "^8.0.0" pacote "9.5.12" semver "7.3.2" @@ -2930,14 +2923,14 @@ integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg== "@types/node@*", "@types/node@>= 8": - version "14.14.13" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.13.tgz#9e425079799322113ae8477297ae6ef51b8e0cdf" - integrity sha512-vbxr0VZ8exFMMAjCW8rJwaya0dMCDyYW2ZRdTyjtrCvJoENMpdUHOT/eTzvgyA5ZnqRZ/sI0NwqAxNHKYokLJQ== + version "14.14.19" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.19.tgz#5135176a8330b88ece4e9ab1fdcfc0a545b4bab4" + integrity sha512-4nhBPStMK04rruRVtVc6cDqhu7S9GZai0fpXgPXrFpcPX6Xul8xnrjSdGB4KPBVYG/R5+fXWdCM8qBoiULWGPQ== "@types/node@^12.11.1": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== + version "12.19.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.11.tgz#9220ab4b20d91169eb78f456dbfcbabee89dfb50" + integrity sha512-bwVfNTFZOrGXyiQ6t4B9sZerMSShWNsGRw8tC5DY1qImUNczS9SjT4G6PnzjCnxsu5Ubj6xjL2lgwddkxtQl5w== "@types/node@^8.0.31": version "8.10.66" @@ -3015,9 +3008,9 @@ source-map "^0.6.1" "@types/yargs-parser@*": - version "15.0.0" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" - integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw== + version "20.2.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9" + integrity sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA== "@types/yargs@^13.0.0": version "13.0.11" @@ -3027,9 +3020,9 @@ "@types/yargs-parser" "*" "@types/yargs@^15.0.0": - version "15.0.11" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.11.tgz#361d7579ecdac1527687bcebf9946621c12ab78c" - integrity sha512-jfcNBxHFYJ4nPIacsi3woz1+kvUO6s1CyeEhtnDHBjHUMNj5UlW2GynmnSgiJJEdNg9yW5C8lfoNRZrHGv5EqA== + version "15.0.12" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.12.tgz#6234ce3e3e3fa32c5db301a170f96a599c960d74" + integrity sha512-f+fD/fQAo3BCbCDlrUpznF1A5Zp9rB0noS5vnoormHSIPFKL0Z2DcUJ3Gxp5ytH4uLRNxy7AwYUC9exZzqGMAw== dependencies: "@types/yargs-parser" "*" @@ -3761,7 +3754,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= -base64-js@^1.0.2: +base64-js@^1.0.2, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -3818,6 +3811,15 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" +bl@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489" + integrity sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + blocking-proxy@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/blocking-proxy/-/blocking-proxy-1.0.1.tgz#81d6fd1fe13a4c0d6957df7f91b75e98dac40cb2" @@ -3987,7 +3989,7 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.15.0, browserslist@^4.7.0, browserslist@^4.9.1: +browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.0, browserslist@^4.7.0, browserslist@^4.9.1: version "4.16.0" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.0.tgz#410277627500be3cb28a1bfe037586fbedf9488b" integrity sha512-/j6k8R0p3nxOC6kx5JGAxsnhc9ixaWJfYc+TNTzxg6+ARaESAvQGV7h0uNOB4t+pLQJZWzcrMxXOxjgsCj3dqQ== @@ -4048,15 +4050,23 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= builtin-modules@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.1.0.tgz#aad97c15131eb76b65b50ef208e7584cd76a7484" - integrity sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw== + version "3.2.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887" + integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA== builtin-status-codes@^3.0.0: version "3.0.0" @@ -4264,9 +4274,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001032, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001165: - version "1.0.30001166" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001166.tgz#ca73e8747acfd16a4fd6c4b784f1b995f9698cf8" - integrity sha512-nCL4LzYK7F4mL0TjEMeYavafOGnBa98vTudH5c8lW9izUjnB99InG6pmC1ElAI1p0GlyZajv4ltUdFXvOHIl1A== + version "1.0.30001173" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001173.tgz#3c47bbe3cd6d7a9eda7f50ac016d158005569f56" + integrity sha512-R3aqmjrICdGCTAnSXtNyvWYMK3YtV5jwudbq0T7nN9k4kmE4CBuwPqyJ+KBzepSTh0huivV2gLbSMEzTTmfeYw== canonical-path@1.0.0: version "1.0.0" @@ -4447,7 +4457,7 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" -cli-spinners@^2.0.0, cli-spinners@^2.2.0, cli-spinners@^2.4.0: +cli-spinners@^2.0.0, cli-spinners@^2.2.0, cli-spinners@^2.4.0, cli-spinners@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.5.0.tgz#12763e47251bf951cb75c201dfa58ff1bcb2d047" integrity sha512-PC+AmIuK04E6aeSs/pUccSujsTzBhu4HzC2dL+CfJB/Jcc2qTRbEwZQDfIUpt2Xl8BodYBEq8w4fc0kU2I9DjQ== @@ -4829,16 +4839,16 @@ conventional-changelog-core@^3.1.6: through2 "^3.0.0" conventional-changelog-core@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-4.2.1.tgz#f811ad98ab2ff080becafc61407509420c9b447d" - integrity sha512-8cH8/DEoD3e5Q6aeogdR5oaaKs0+mG6+f+Om0ZYt3PNv7Zo0sQhu4bMDRsqAF+UTekTAtP1W/C41jH/fkm8Jtw== + version "4.2.2" + resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-4.2.2.tgz#f0897df6d53b5d63dec36b9442bd45354f8b3ce5" + integrity sha512-7pDpRUiobQDNkwHyJG7k9f6maPo9tfPzkSWbRq97GGiZqisElhnvUZSvyQH20ogfOjntB5aadvv6NNcKL1sReg== dependencies: add-stream "^1.0.0" conventional-changelog-writer "^4.0.18" conventional-commits-parser "^3.2.0" dateformat "^3.0.0" get-pkg-repo "^1.0.0" - git-raw-commits "2.0.0" + git-raw-commits "^2.0.8" git-remote-origin-url "^2.0.0" git-semver-tags "^4.1.1" lodash "^4.17.15" @@ -4891,9 +4901,9 @@ conventional-changelog-preset-loader@^2.1.1, conventional-changelog-preset-loade integrity sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g== conventional-changelog-writer@^4.0.18, conventional-changelog-writer@^4.0.6: - version "4.0.18" - resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.18.tgz#10b73baa59c7befc69b360562f8b9cd19e63daf8" - integrity sha512-mAQDCKyB9HsE8Ko5cCM1Jn1AWxXPYV0v8dFPabZRkvsiWUul2YyAqbIaoMKF88Zf2ffnOPSvKhboLf3fnjo5/A== + version "4.1.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.1.0.tgz#1ca7880b75aa28695ad33312a1f2366f4b12659f" + integrity sha512-WwKcUp7WyXYGQmkLsX4QmU42AZ1lqlvRW9mqoyiQzdD+rJWbTepdWoKJuwXTS+yq79XKnQNa93/roViPQrAQgw== dependencies: compare-func "^2.0.0" conventional-commits-filter "^2.0.7" @@ -4990,6 +5000,13 @@ cookie@0.4.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== +copy-anything@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-2.0.1.tgz#2afbce6da684bdfcbec93752fa762819cb480d9a" + integrity sha512-lA57e7viQHOdPQcrytv5jFeudZZOXuyk47lZym279FiDQ8jeZomXiGuVf6ffMKkJ+3TIai3J1J3yi6M+/4U35g== + dependencies: + is-what "^3.7.1" + copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -5025,11 +5042,11 @@ copy-webpack-plugin@6.2.1: webpack-sources "^1.4.3" core-js-compat@^3.6.2: - version "3.8.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.8.1.tgz#8d1ddd341d660ba6194cbe0ce60f4c794c87a36e" - integrity sha512-a16TLmy9NVD1rkjUGbwuyWkiDoN0FDpAwrfLONvHFQx0D9k7J9y0srwMT8QP/Z6HE3MIFaVynEeYwZwPX1o5RQ== + version "3.8.2" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.8.2.tgz#3717f51f6c3d2ebba8cbf27619b57160029d1d4c" + integrity sha512-LO8uL9lOIyRRrQmZxHZFl1RV+ZbcsAkFWTktn5SmH40WgLtSNYN4m4W2v9ONT147PxBY/XrRhrWq8TlvObyUjQ== dependencies: - browserslist "^4.15.0" + browserslist "^4.16.0" semver "7.0.0" core-js@3.6.5: @@ -5398,6 +5415,11 @@ dargs@^4.0.1: dependencies: number-is-nan "^1.0.0" +dargs@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc" + integrity sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg== + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -5811,9 +5833,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.621: - version "1.3.626" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.626.tgz#48acdf322be07feb2c1330ba05e4bf6327f721a3" - integrity sha512-7CanEvJx74EnvjHu1X8gf93KieyxvFLnqOXAH/ddjWD4RrUZYqdg3pykrQ/7t6SLI7DTsp4tfQXEfzeK5t6oAw== + version "1.3.633" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.633.tgz#16dd5aec9de03894e8d14a1db4cda8a369b9b7fe" + integrity sha512-bsVCsONiVX1abkWdH7KtpuDAhsQ3N3bjPYhROSAXE78roJKet0Y5wznA14JE9pzbwSZmSMAW6KiKYf1RvbTJkA== elliptic@^6.5.3: version "6.5.3" @@ -5905,9 +5927,9 @@ err-code@^1.0.0: integrity sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA= errno@^0.1.1, errno@^0.1.3, errno@~0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== dependencies: prr "~1.0.1" @@ -6349,9 +6371,9 @@ fastparse@^1.1.2: integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== fastq@^1.6.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.9.0.tgz#e16a72f338eaca48e91b5c23593bcc2ef66b7947" - integrity sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w== + version "1.10.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.10.0.tgz#74dbefccade964932cdf500473ef302719c652bb" + integrity sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA== dependencies: reusify "^1.0.4" @@ -6691,9 +6713,9 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-intrinsic@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz#94a9768fcbdd0595a1c9273aacf4c89d075631be" - integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg== + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.2.tgz#6820da226e50b24894e08859469dc68361545d49" + integrity sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg== dependencies: function-bind "^1.1.1" has "^1.0.3" @@ -6762,6 +6784,17 @@ git-raw-commits@2.0.0: split2 "^2.0.0" through2 "^2.0.0" +git-raw-commits@^2.0.8: + version "2.0.9" + resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.9.tgz#5cbc707a615cb77b71e687f8a1ee54af46208b22" + integrity sha512-hSpNpxprVno7IOd4PZ93RQ+gNdzPAIrW0x8av6JQDJGV4k1mR9fE01dl8sEqi2P7aKmmwiGUn1BCPuf16Ae0Qw== + dependencies: + dargs "^7.0.0" + lodash.template "^4.0.2" + meow "^8.0.0" + split2 "^3.0.0" + through2 "^4.0.0" + git-remote-origin-url@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f" @@ -7155,9 +7188,9 @@ html-encoding-sniffer@^1.0.2: whatwg-encoding "^1.0.1" html-entities@^1.3.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.3.3.tgz#3dca638a43ee7de316fc23067398491152ad4736" - integrity sha512-/VulV3SYni1taM7a4RMdceqzJWR39gpZHjBwUnsCFKWV/GJkD14CJ5F7eWcZozmHJK0/f/H5U3b3SiPkuvxMgg== + version "1.4.0" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc" + integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA== html-escaper@^2.0.0: version "2.0.2" @@ -7212,9 +7245,9 @@ http-errors@~1.7.2: toidentifier "1.0.0" http-parser-js@>=0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.2.tgz#da2e31d237b393aae72ace43882dd7e270a8ff77" - integrity sha512-opCO9ASqg5Wy2FNo7A0sxy71yGbbkJJXLdgMK04Tcypw9jr2MgWbyubb0+WdmDmGnFflO7fRbqbaihh/ENDlRQ== + version "0.5.3" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" + integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== http-proxy-agent@^2.1.0: version "2.1.0" @@ -7306,7 +7339,7 @@ icss-utils@^4.0.0, icss-utils@^4.1.1: dependencies: postcss "^7.0.14" -ieee754@^1.1.4: +ieee754@^1.1.13, ieee754@^1.1.4: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -7352,9 +7385,9 @@ import-fresh@^2.0.0: resolve-from "^3.0.0" import-fresh@^3.0.0, import-fresh@^3.2.1: - version "3.2.2" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.2.tgz#fc129c160c5d68235507f4331a6baad186bdbc3e" - integrity sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw== + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" @@ -7430,10 +7463,10 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== +ini@1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.6.tgz#f1c46a2a93a253e7b3905115e74d527cd23061a1" + integrity sha512-IZUoxEjNjubzrmvzZU4lKP7OnYmX72XRl3sqkfJhBKweKi5rnGi5+IUdlj/H1M+Ip5JQ1WzaDMOBRY90Ajc5jg== ini@^1.3.2, ini@^1.3.4: version "1.3.8" @@ -7894,6 +7927,11 @@ is-utf8@^0.2.0, is-utf8@^0.2.1: resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= +is-what@^3.7.1: + version "3.12.0" + resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.12.0.tgz#f4405ce4bd6dd420d3ced51a026fb90e03705e55" + integrity sha512-2ilQz5/f/o9V7WRWJQmpFYNmQFZ9iM+OXRonZKcYgTkCzjb949Vi4h282PD1UfmgHk666rcWonbRJ++KI41VGw== + is-windows@^1.0.0, is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -8708,10 +8746,11 @@ less@3.12.2: source-map "~0.6.0" less@^3.10.3: - version "3.13.0" - resolved "https://registry.yarnpkg.com/less/-/less-3.13.0.tgz#6a47bb19d97edcf7a53d444b099275dd6b17c85a" - integrity sha512-uPhr9uoSGVKKYVGz0rXcYBK1zjwcIWRGcbnSgNt66XuIZYrYPaQiS+LeUOvqedBwrwdBYYaLqSff5ytGYuT7rA== + version "3.13.1" + resolved "https://registry.yarnpkg.com/less/-/less-3.13.1.tgz#0ebc91d2a0e9c0c6735b83d496b0ab0583077909" + integrity sha512-SwA1aQXGUvp+P5XdZslUOhhLnClSLIjWvJhmd+Vgib5BFIr9lMNlQwmwUNOjXThF/A0x+MCYYPeWEfeWiLRnTw== dependencies: + copy-anything "^2.0.1" tslib "^1.10.0" optionalDependencies: errno "^0.1.1" @@ -9141,9 +9180,9 @@ meow@^4.0.0: trim-newlines "^2.0.0" meow@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-8.0.0.tgz#1aa10ee61046719e334ffdc038bb5069250ec99a" - integrity sha512-nbsTRz2fwniJBFgUkcdISq8y/q9n9VbiHYbfwklFh5V4V2uAcxtKQkDc0yCLPM/kP0d+inZBewn3zJqewHE7kg== + version "8.1.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.0.tgz#0fcaa267e35e4d58584b8205923df6021ddcc7ba" + integrity sha512-fNWkgM1UVMey2kf24yLiccxLihc5W+6zVus3/N0b+VfnJgxV99E9u04X6NAiKdg6ED7DAQBX5sy36NM0QJZkWA== dependencies: "@types/minimist" "^1.2.0" camelcase-keys "^6.2.2" @@ -9224,22 +9263,17 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.44.0: - version "1.44.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" - integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== - -"mime-db@>= 1.43.0 < 2": +mime-db@1.45.0, "mime-db@>= 1.43.0 < 2": version "1.45.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: - version "2.1.27" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" - integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== + version "2.1.28" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" + integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== dependencies: - mime-db "1.44.0" + mime-db "1.45.0" mime@1.6.0, mime@^1.4.1: version "1.6.0" @@ -9247,9 +9281,9 @@ mime@1.6.0, mime@^1.4.1: integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== mime@^2.3.1, mime@^2.4.4: - version "2.4.6" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1" - integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA== + version "2.4.7" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.7.tgz#962aed9be0ed19c91fd7dc2ece5d7f4e89a90d74" + integrity sha512-dhNd1uA2u397uQk3Nv5LM4lm93WYDUXFn3Fu291FJerns4jyTudqhIWe4W04YLy7Uk1tm1Ore04NpjRvQp/NPA== mimic-fn@^1.0.0: version "1.2.0" @@ -9589,9 +9623,9 @@ ng-packagr@^11.0.1: terser "^5.0.0" ng-zorro-antd@^10.1.1: - version "10.2.1" - resolved "https://registry.yarnpkg.com/ng-zorro-antd/-/ng-zorro-antd-10.2.1.tgz#06d9c2db7f92bdd560c98c201114b2fc2318af23" - integrity sha512-G1w/Gs2Qgsoyf9c+t1uyQkZ07ayiOoH4waS8CP+IEvlCe0fZ02V0IFjS6NLrTpDxw7qDBIykI+qcWEY14GIF8A== + version "10.2.2" + resolved "https://registry.yarnpkg.com/ng-zorro-antd/-/ng-zorro-antd-10.2.2.tgz#5951f1fd5d1e405e7fe983756dca1eb942b255de" + integrity sha512-4Q2G6DtRJnEQXFcIEUyqgFi6JXcEF9bN0zOPNBV7LTNgjOf31QiE+3Pu2ifz8esGVwv7vmG8if8V2/Ha/Ol8Dw== dependencies: "@angular/cdk" "^10.2.4" "@ant-design/icons-angular" "^10.0.0" @@ -10085,7 +10119,7 @@ ora@5.0.0: strip-ansi "^6.0.0" wcwidth "^1.0.1" -ora@5.1.0, ora@^5.1.0: +ora@5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/ora/-/ora-5.1.0.tgz#b188cf8cd2d4d9b13fd25383bc3e5cba352c94f8" integrity sha512-9tXIMPvjZ7hPTbk8DFq1f7Kow/HU/pQYB60JbNq+QnGwcyhWVZaQ4hM9zQDEsPxw/muLpgiHSaumUZxCAmod/w== @@ -10111,6 +10145,20 @@ ora@^3.4.0: strip-ansi "^5.2.0" wcwidth "^1.0.1" +ora@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.2.0.tgz#de10bfd2d15514384af45f3fa9d9b1aaf344fda1" + integrity sha512-+wG2v8TUU8EgzPHun1k/n45pXquQ9fHnbXVetl9rRgO6kjZszGGbraF3XPTIdgeA+s1lbRjSEftAnyT0w8ZMvQ== + dependencies: + bl "^4.0.3" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + log-symbols "^4.0.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + original@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" @@ -11371,7 +11419,7 @@ read@1, read@~1.0.1: string_decoder "~1.1.1" util-deprecate "~1.0.1" -"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.6.0: +"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -11921,9 +11969,9 @@ sass@1.27.0: chokidar ">=2.0.0 <4.0.0" sass@^1.23.0: - version "1.30.0" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.30.0.tgz#60bbbbaf76ba10117e61c6c24f00161c3d60610e" - integrity sha512-26EUhOXRLaUY7+mWuRFqGeGGNmhB1vblpTENO1Z7mAzzIZeVxZr9EZoaY1kyGLFWdSOZxRMAufiN2mkbO6dAlw== + version "1.32.0" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.32.0.tgz#10101a026c13080b14e2b374d4e15ee24400a4d3" + integrity sha512-fhyqEbMIycQA4blrz/C0pYhv2o4x2y6FYYAH0CshBw3DXh5D5wyERgxw0ptdau1orc/GhNrhF7DFN2etyOCEng== dependencies: chokidar ">=2.0.0 <4.0.0" @@ -12442,6 +12490,13 @@ split2@^2.0.0: dependencies: through2 "^2.0.2" +split2@^3.0.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" + integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg== + dependencies: + readable-stream "^3.0.0" + split@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" @@ -13350,9 +13405,9 @@ typescript@^3.5.2, typescript@~3.9.2: integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== uglify-js@^3.1.4: - version "3.12.1" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.12.1.tgz#78307f539f7b9ca5557babb186ea78ad30cc0375" - integrity sha512-o8lHP20KjIiQe5b/67Rh68xEGRrc2SRsCuuoYclXXoC74AfSRGblU1HKzJWH3HxPZ+Ort85fWHpSX7KwBUC9CQ== + version "3.12.4" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.12.4.tgz#93de48bb76bb3ec0fc36563f871ba46e2ee5c7ee" + integrity sha512-L5i5jg/SHkEqzN18gQMTWsZk3KelRsfD1wUVNqtq0kzqWQqcJjyL8yc1o8hJgRrWqrAl2mUFbhfznEIoi7zi2A== uid-number@0.0.6: version "0.0.6" @@ -13702,7 +13757,7 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== -webpack-dev-middleware@3.7.2, webpack-dev-middleware@^3.7.2: +webpack-dev-middleware@3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz#0019c3db716e3fa5cecbf64f2ab88a74bab331f3" integrity sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw== @@ -13713,6 +13768,17 @@ webpack-dev-middleware@3.7.2, webpack-dev-middleware@^3.7.2: range-parser "^1.2.1" webpack-log "^2.0.0" +webpack-dev-middleware@^3.7.2: + version "3.7.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5" + integrity sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ== + dependencies: + memory-fs "^0.4.1" + mime "^2.4.4" + mkdirp "^0.5.1" + range-parser "^1.2.1" + webpack-log "^2.0.0" + webpack-dev-server@3.11.0: version "3.11.0" resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz#8f154a3bce1bcfd1cc618ef4e703278855e7ff8c" @@ -14015,9 +14081,9 @@ ws@^6.2.1: async-limiter "~1.0.0" ws@^7.0.0: - version "7.4.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.1.tgz#a333be02696bd0e54cea0434e21dcc8a9ac294bb" - integrity sha512-pTsP8UAfhy3sk1lSk/O/s4tjD0CRwvMnzvwr4OKGX7ZvqZtUyx4KIJB5JWbkykPoc55tixMGgTNoh3k4FkNGFQ== + version "7.4.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.2.tgz#782100048e54eb36fe9843363ab1c68672b261dd" + integrity sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA== xml-name-validator@^3.0.0: version "3.0.0" diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/appsettings.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/appsettings.json index 1d9beacd54..b9ba4298dd 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/appsettings.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/appsettings.json @@ -1,6 +1,6 @@ { "ConnectionStrings": { - "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True" }, "IdentityServer": { "Clients": { diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/appsettings.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/appsettings.json index 6c64a7b397..12bd4f78bb 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/appsettings.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/appsettings.json @@ -3,7 +3,7 @@ "CorsOrigins": "https://*.MyProjectName.com,http://localhost:4200,https://localhost:44307" }, "ConnectionStrings": { - "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True" }, "Redis": { "Configuration": "127.0.0.1" diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/appsettings.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/appsettings.json index 1051a8576c..73d80aeec4 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/appsettings.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/appsettings.json @@ -5,7 +5,7 @@ "RedirectAllowedUrls": "http://localhost:4200,https://localhost:44307" }, "ConnectionStrings": { - "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True" }, "AuthServer": { "Authority": "https://localhost:44305", diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/appsettings.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/appsettings.json index c7101f92ed..0e667e5d73 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/appsettings.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/appsettings.json @@ -5,7 +5,7 @@ "RedirectAllowedUrls": "http://localhost:4200,https://localhost:44307" }, "ConnectionStrings": { - "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True" }, "Redis": { "Configuration": "127.0.0.1" diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/appsettings.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/appsettings.json index 8084875aa5..9c81e66699 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/appsettings.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/appsettings.json @@ -3,7 +3,7 @@ "SelfUrl": "https://localhost:44303" }, "ConnectionStrings": { - "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True" }, "AuthServer": { "Authority": "https://localhost:44303", diff --git a/templates/module/aspnet-core/docker-compose.override.yml b/templates/module/aspnet-core/docker-compose.override.yml index 8d583bacd7..061757bb76 100644 --- a/templates/module/aspnet-core/docker-compose.override.yml +++ b/templates/module/aspnet-core/docker-compose.override.yml @@ -11,19 +11,19 @@ services: identity-server: environment: - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionStrings__Default=Server=sqlserver;Database=MyProjectName_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false - - ConnectionStrings__SqlServerCache=Server=sqlserver;Database=MyProjectName_Cache;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__Default=Server=sqlserver;Database=MyProjectName_Identity;Trusted_Connection=True;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__SqlServerCache=Server=sqlserver;Database=MyProjectName_Cache;Trusted_Connection=True;User=sa;Password=yourStrong(!)Password;Integrated Security=false ports: - "51600:80" my-project-name: environment: - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionStrings__Default=Server=sqlserver;Database=MyProjectName_ModuleDb;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false - - ConnectionStrings__AbpSettingManagement=Server=sqlserver;Database=MyProjectName_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false - - ConnectionStrings__AbpPermissionManagement=Server=sqlserver;Database=MyProjectName_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false - - ConnectionStrings__AbpAuditLogging=Server=sqlserver;Database=MyProjectName_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false - - ConnectionStrings__SqlServerCache=Server=sqlserver;Database=MyProjectName_Cache;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__Default=Server=sqlserver;Database=MyProjectName_ModuleDb;Trusted_Connection=True;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__AbpSettingManagement=Server=sqlserver;Database=MyProjectName_Identity;Trusted_Connection=True;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__AbpPermissionManagement=Server=sqlserver;Database=MyProjectName_Identity;Trusted_Connection=True;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__AbpAuditLogging=Server=sqlserver;Database=MyProjectName_Identity;Trusted_Connection=True;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__SqlServerCache=Server=sqlserver;Database=MyProjectName_Cache;Trusted_Connection=True;User=sa;Password=yourStrong(!)Password;Integrated Security=false - AuthServer__Authority=http://identity-server ports: - "51601:80" \ No newline at end of file diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/appsettings.json b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/appsettings.json index d80fc69b59..b35a5997cf 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/appsettings.json +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/appsettings.json @@ -3,8 +3,8 @@ "CorsOrigins": "https://*.MyProjectName.com,http://localhost:4200,http://localhost:44307,https://localhost:44307" }, "ConnectionStrings": { - "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName_Main;Trusted_Connection=True;MultipleActiveResultSets=true", - "MyProjectName": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName_Module;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName_Main;Trusted_Connection=True", + "MyProjectName": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName_Module;Trusted_Connection=True" }, "Redis": { "Configuration": "127.0.0.1" diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/appsettings.json b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/appsettings.json index dd966995a3..29608e57a4 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/appsettings.json +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/appsettings.json @@ -5,7 +5,7 @@ }, "AppSelfUrl": "https://localhost:44301/", "ConnectionStrings": { - "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName_Main;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName_Main;Trusted_Connection=True" }, "Redis": { "Configuration": "127.0.0.1" diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/appsettings.json b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/appsettings.json index e081a57a67..f90c5b2d28 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/appsettings.json +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/appsettings.json @@ -1,5 +1,5 @@ { "ConnectionStrings": { - "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName_Unified;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName_Unified;Trusted_Connection=True" } } \ No newline at end of file diff --git a/test/AbpPerfTest/AbpPerfTest.WithAbp/AppModule.cs b/test/AbpPerfTest/AbpPerfTest.WithAbp/AppModule.cs index 1cd88989e6..3846cdd3de 100644 --- a/test/AbpPerfTest/AbpPerfTest.WithAbp/AppModule.cs +++ b/test/AbpPerfTest/AbpPerfTest.WithAbp/AppModule.cs @@ -33,7 +33,7 @@ namespace AbpPerfTest.WithAbp Configure(options => { - options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; + options.TransactionBehavior = UnitOfWorkTransactionBehavior.Auto; }); } diff --git a/test/AbpPerfTest/AbpPerfTest.WithAbp/Controllers/BookController.cs b/test/AbpPerfTest/AbpPerfTest.WithAbp/Controllers/BookController.cs index 7c78937342..1533e95f71 100644 --- a/test/AbpPerfTest/AbpPerfTest.WithAbp/Controllers/BookController.cs +++ b/test/AbpPerfTest/AbpPerfTest.WithAbp/Controllers/BookController.cs @@ -5,7 +5,6 @@ using System.Threading.Tasks; using AbpPerfTest.WithAbp.Dtos; using AbpPerfTest.WithAbp.Entities; using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; using Volo.Abp.Domain.Repositories; namespace AbpPerfTest.WithAbp.Controllers @@ -23,7 +22,7 @@ namespace AbpPerfTest.WithAbp.Controllers [HttpGet] public async Task> GetListAsync() { - var books = await _bookRepository.OrderBy(x => x.Id).Take(10).ToListAsync(); + var books = await _bookRepository.GetPagedListAsync(0, 10, "Id"); return books .Select(b => new BookDto diff --git a/test/AbpPerfTest/AbpPerfTest.WithAbp/appsettings.json b/test/AbpPerfTest/AbpPerfTest.WithAbp/appsettings.json index 9cd22c72c3..3508332bef 100644 --- a/test/AbpPerfTest/AbpPerfTest.WithAbp/appsettings.json +++ b/test/AbpPerfTest/AbpPerfTest.WithAbp/appsettings.json @@ -1,13 +1,13 @@ { "Logging": { "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", + "Default": "Error", + "Microsoft": "Error", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "ConnectionStrings": { - "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=AbpPerfTest_WithAbp;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=AbpPerfTest_WithAbp;Trusted_Connection=True" } } diff --git a/test/AbpPerfTest/AbpPerfTest.WithoutAbp/appsettings.json b/test/AbpPerfTest/AbpPerfTest.WithoutAbp/appsettings.json index 7f6ca466b2..0a5a9029ec 100644 --- a/test/AbpPerfTest/AbpPerfTest.WithoutAbp/appsettings.json +++ b/test/AbpPerfTest/AbpPerfTest.WithoutAbp/appsettings.json @@ -8,6 +8,6 @@ }, "AllowedHosts": "*", "ConnectionStrings": { - "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=AbpPerfTest_WithoutAbp;Trusted_Connection=True;MultipleActiveResultSets=true" + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=AbpPerfTest_WithoutAbp;Trusted_Connection=True" } } diff --git a/test/AbpPerfTest/_jmeter/SimpleTestPlan.jmx b/test/AbpPerfTest/_jmeter/SimpleTestPlan.jmx index 24327e6e14..0c08c60f20 100644 --- a/test/AbpPerfTest/_jmeter/SimpleTestPlan.jmx +++ b/test/AbpPerfTest/_jmeter/SimpleTestPlan.jmx @@ -16,9 +16,9 @@ continue false - 100 + 20 - 100 + 2000 10 false @@ -84,7 +84,7 @@ - + true @@ -115,7 +115,7 @@ - + diff --git a/test/AbpPerfTest/_jmeter/SimpleTestPlanWithoutAbp.jmx b/test/AbpPerfTest/_jmeter/SimpleTestPlanWithoutAbp.jmx index 39f188daf3..c7d6b3292c 100644 --- a/test/AbpPerfTest/_jmeter/SimpleTestPlanWithoutAbp.jmx +++ b/test/AbpPerfTest/_jmeter/SimpleTestPlanWithoutAbp.jmx @@ -16,9 +16,9 @@ continue false - 100 + 20 - 100 + 500 10 false @@ -84,7 +84,7 @@ - + true @@ -115,7 +115,7 @@ - +