Browse Source

Merge pull request #9266 from abpframework/auto-merge/rel-4-3/432

Merge branch dev with rel-4.3
pull/9276/head
maliming 5 years ago
committed by GitHub
parent
commit
5ab37c78e4
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      docs/en/Domain-Driven-Design.md
  2. 11
      docs/en/Index.md
  3. BIN
      docs/en/images/implementing-domain-driven-design-book.png
  4. 23
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
  5. 46
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Auditing/Auditing_Tests.cs
  6. 13
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs
  7. 8
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs
  8. 5
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs

4
docs/en/Domain-Driven-Design.md

@ -32,6 +32,6 @@ DDD mostly interest in the **Domain** and the **Application** layers, rather tha
* [Data Transfer Objects (DTOs)](Data-Transfer-Objects.md)
* [Unit of Work](Unit-Of-Work.md)
## The Ultimate DDD Implementation Guide
## Free E-Book: Implementing DDD
See the [Implementing Domain Driven Design](Domain-Driven-Design-Implementation-Guide.md) guide as a **complete reference**. The Guide explains the Domain Driven Design and introduces explicit **rules and examples** to give a deep understanding of the **implementation details**.
See the [Implementing Domain Driven Design book](https://abp.io/books/implementing-domain-driven-design) as a **complete reference**. This book explains the Domain Driven Design and introduces explicit **rules and examples** to give a deep understanding of the **implementation details**.

11
docs/en/Index.md

@ -29,8 +29,9 @@ ABP has a **comprehensive documentation** that not only explains the ABP Framewo
ABP offers a complete, modular and layered software architecture based on [Domain Driven Design](Domain-Driven-Design.md) principles and patterns. It also provides the necessary infrastructure to implement this architecture.
* See the [Modularity](Module-Development-Basics.md) document to understand the module system.
* [Implementing Domain Driven Design](Domain-Driven-Design-Implementation-Guide.md) document is an ultimate guide for who want to understand and implement the DDD.
* [Implementing Domain Driven Design book](https://abp.io/books/implementing-domain-driven-design?ref=doc) is an ultimate guide for who want to understand and implement the DDD with the ABP Framework.
* [Microservice Architecture](Microservice-Architecture.md) document explains how ABP helps to create a microservice solution.
* [Multi-Tenancy](Multi-Tenancy.md) document introduces multi-tenancy and explores the ABP multi-tenancy infrastructure.
### Infrastructure
@ -55,6 +56,14 @@ See the [Application Modules](Modules/Index.md) document for all pre-built modul
The [Startup templates](Startup-Templates/Index.md) are pre-built Visual Studio solution templates. You can create your own solution based on these templates to **immediately start your development**.
## Free E-Book: Implementing Domain Driven Design
![Implementing Domain Driven Design](images/implementing-domain-driven-design-book.png)
A **practical guide** for implementing Domain Driven Design (DDD). While the implementation details are **based on the ABP Framework** infrastructure, the basic concepts, principles and models can be applied to any solution, even if it is not a .NET solution.
[Click here to get your free copy](https://abp.io/books/implementing-domain-driven-design?ref=doc).
## ABP Community
### The Source Code

BIN
docs/en/images/implementing-domain-driven-design-book.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

23
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs

@ -371,17 +371,20 @@ namespace Volo.Abp.EntityFrameworkCore
protected virtual void ApplyAbpConceptsForModifiedEntity(EntityEntry entry, EntityChangeReport changeReport)
{
UpdateConcurrencyStamp(entry);
SetModificationAuditProperties(entry);
if (entry.Entity is ISoftDelete && entry.Entity.As<ISoftDelete>().IsDeleted)
{
SetDeletionAuditProperties(entry);
changeReport.ChangedEntities.Add(new EntityChangeEntry(entry.Entity, EntityChangeType.Deleted));
}
else
if (entry.State == EntityState.Modified && entry.Properties.Any(x => x.IsModified && x.Metadata.ValueGenerated == ValueGenerated.Never))
{
changeReport.ChangedEntities.Add(new EntityChangeEntry(entry.Entity, EntityChangeType.Updated));
UpdateConcurrencyStamp(entry);
SetModificationAuditProperties(entry);
if (entry.Entity is ISoftDelete && entry.Entity.As<ISoftDelete>().IsDeleted)
{
SetDeletionAuditProperties(entry);
changeReport.ChangedEntities.Add(new EntityChangeEntry(entry.Entity, EntityChangeType.Deleted));
}
else
{
changeReport.ChangedEntities.Add(new EntityChangeEntry(entry.Entity, EntityChangeType.Updated));
}
}
}

46
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Auditing/Auditing_Tests.cs

@ -1,9 +1,53 @@
using Volo.Abp.TestApp.Testing;
using System;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.TestApp;
using Volo.Abp.TestApp.Testing;
using Xunit;
namespace Volo.Abp.EntityFrameworkCore.Auditing
{
public class Auditing_Tests : Auditing_Tests<AbpEntityFrameworkCoreTestModule>
{
[Fact]
public async Task Should_Not_Set_Modification_If_Properties_Generated_By_Database()
{
await WithUnitOfWorkAsync((async () =>
{
var douglas = await PersonRepository.GetAsync(TestDataBuilder.UserDouglasId);
douglas.LastActiveTime = DateTime.Now;
}));
await WithUnitOfWorkAsync((async () =>
{
var douglas = await PersonRepository.FindAsync(TestDataBuilder.UserDouglasId);
douglas.ShouldNotBeNull();
douglas.LastModificationTime.ShouldBeNull();
douglas.LastModificationTime.ShouldBeNull();
douglas.LastModifierId.ShouldBeNull();
}));
}
[Fact]
public async Task Should_Set_Modification_If_Properties_Not_Generated_By_Database()
{
await WithUnitOfWorkAsync((async () =>
{
var douglas = await PersonRepository.GetAsync(TestDataBuilder.UserDouglasId);
douglas.LastActiveTime = DateTime.Now;
douglas.Age = 100;
}));
await WithUnitOfWorkAsync((async () =>
{
var douglas = await PersonRepository.FindAsync(TestDataBuilder.UserDouglasId);
douglas.ShouldNotBeNull();
douglas.LastModificationTime.ShouldNotBeNull();
douglas.LastModificationTime.Value.ShouldBeLessThanOrEqualTo(Clock.Now);
douglas.LastModifierId.ShouldBe(CurrentUserId);
}));
}
}
}

13
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs

@ -1,3 +1,4 @@
using System;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.TestApp.SecondContext;
using Volo.Abp.EntityFrameworkCore.TestApp.ThirdDbContext;
@ -16,10 +17,10 @@ namespace Volo.Abp.EntityFrameworkCore
public DbSet<BookInSecondDbContext> Books { get; set; }
public DbSet<EntityWithIntPk> EntityWithIntPks { get; set; }
public DbSet<Author> Author { get; set; }
public TestMigrationsDbContext(DbContextOptions<TestMigrationsDbContext> options)
public TestMigrationsDbContext(DbContextOptions<TestMigrationsDbContext> options)
: base(options)
{
@ -36,6 +37,12 @@ namespace Volo.Abp.EntityFrameworkCore
b.HasKey(p => new { p.PersonId, p.Number });
});
modelBuilder.Entity<Person>(b =>
{
b.Property(x => x.LastActiveTime).ValueGeneratedOnAddOrUpdate().HasDefaultValue(DateTime.Now);
});
modelBuilder.Entity<City>(b =>
{
b.OwnsMany(c => c.Districts, d =>

8
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore;
using System;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.Modeling;
@ -46,6 +47,11 @@ namespace Volo.Abp.TestApp.EntityFrameworkCore
b.ApplyObjectExtensionMappings();
});
modelBuilder.Entity<Person>(b =>
{
b.Property(x => x.LastActiveTime).ValueGeneratedOnAddOrUpdate().HasDefaultValue(DateTime.Now);
});
modelBuilder
.Entity<PersonView>(p =>
{

5
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs

@ -23,9 +23,10 @@ namespace Volo.Abp.TestApp.Domain
public virtual Collection<Phone> Phones { get; set; }
public virtual DateTime LastActiveTime { get; set; }
private Person()
{
}
public Person(Guid id, string name, int age, Guid? tenantId = null, Guid? cityId = null)
@ -65,4 +66,4 @@ namespace Volo.Abp.TestApp.Domain
);
}
}
}
}

Loading…
Cancel
Save