After the previous article covered the advantages of classic DDD over traditional three-tier architectures and the responsibilities of each layer of the classic DDD architecture, this article will introduce the main code for the lightweight framework that supports DDD in the infrastructure layer.

It is important to note that the DDD lightweight framework can reflect the idea of DDD, but it does not have to be heavy, you can also understand the implementation of DDD support framework.

1. Top-level representations of entities, aggregate roots, and value objects

Entity top-level definition:

public interface IEntity { string Code { get; set; } Guid Id { get; set; }}Copy the code

Id is a technical primary key that will be stored in the database table, and Code is the unique business identifier for the domain object. You can also extend this interface to define the interface for comparing two entities (a future implementation would compare two entities equal if the codes are the same).

Aggregate root top-level definition:

public interface IAggregationRoot:IEntity
{

}
Copy the code

The aggregate root interface is inherited from the entity interface, but the domain objects that future usage can define persistence in the repository must be inherited from this interface or from the abstract class that inherits the interface.

Value object top-level definition:

public interface IValueObject { Guid Id { get; set; }}Copy the code

The value object interface only needs to retain a technical primary key; it has no business identifier. In a database, value objects may be stored as separate tables or as part of an entity. You can also extend this interface by defining the interface for comparing two value objects (a future implementation would be to compare two value objects equal if all attribute values are the same).

Top level definition of unit of work:

public interface IUnitOfWork
{
    void Commit();
}
Copy the code

The unit-of work interface defines a commit method, which, when implemented, is the entire aggregated transaction commit method of the corresponding EFCore.

Warehouse interface top-level definition:

public interface IRepository:IUnitOfWork,IDisposable
{
}
Copy the code

Warehouse interfaces inherit from unit-of-work interfaces and resource release interfaces, providing top-level constraints for future data access frameworks and replaceability.

EF Core top-level storage persistence implementation:

public class EFCoreRepository : IRepository { private readonly DbContext context; public EFCoreRepository(DbContext context) { this.context = context; } public void Commit() { try { context.SaveChanges(); } catch(Exception error) { throw error; } } public void Dispose() { context.Dispose(); }}Copy the code

As you can see from the above code, the main implementation of the warehouse interface Commit method is the SaveChanges() transaction Commit method of the EF Core DbContext data access context class. The application service layer use case can obtain the current state of an aggregation root. The Commit method of the repository interface is then called to implement a one-time transaction Commit for all objects in the aggregate.

2. Implementation of common tool classes

Asp.net Core Json configuration file reading, Json serialization and deserialization, encryption, dependency injection, object format definition returned to the front end, etc. Here are a few of the requirements. Others will be supplemented in later specific cases.

Asp.netCore Json configuration file read:

Json configuration files will store some of our configuration information, such as database connection string, wechat AppId and AppSecure, so it is necessary to have a function to support the Key to Value reading of Json configuration files

public class AppSetting
{
    private static IConfigurationSection appsections = null;
    public static void SetAppSetting(IConfigurationSection section)
    {
        appsections = section;
    }
    public static string GetAppSetting(string key)
    {
        string str = "";
        if (appsections.GetSection(key) != null)
        {
            str = appsections.GetSection(key).Value;
        }
        return str;
    }
}
Copy the code

Return the object format definition of the front end: Our application service layer will return a certain data format to the WebApi interface, and the WebApi interface will also return this data to the front end, and the front end will do the corresponding processing after it gets it.

public class ResultEntity<T> { public bool IsSuccess { get; set; } public string Msg { get; set; } public T Data { get; set; } public int ErrorCode { get; set; } public int Count { get; set; }} public class BaseAppSrv {protected ResultEntity<T> GetResultEntity<T>(T vobj,string MSG =" failed to obtain object ",int errorCode = 0) { var ueresult = new ResultEntity<T>(); var issuccess = true; if(vobj is int && Convert.ToInt32(vobj) <= 0) { issuccess = false; } else if(vobj is bool && ! Convert.ToBoolean(vobj)) { issuccess = false; } else if(vobj is string && string.IsNullOrEmpty(Convert.ToString(vobj))) { issuccess = false; } if (! issuccess) { ueresult.Msg = msg; ueresult.ErrorCode = 200; } ueresult.IsSuccess = issuccess; ueresult.Data = vobj; return ueresult; }}Copy the code

All future use cases will inherit from BaseAppSrv and return ResultEntity.

Ok, the basic framework set up, the next chapter can directly into the case, see how to design through DDD ideas, and through the classic DDD architecture and DDD lightweight framework for the actual business system code.

DDD combat advanced video please pay attention to wechat public number: MSSHCJ