简体   繁体   中英

.Net architecture Clean Architecture question on Persistence layer and InternalsVisibleTo

Suppose, I have an Entity with read-only Id property, like:

public int Id { get; }

And then I have a Persistence layer which implements entity repository and assigns new Id value when Entity is stored to db:

public async Task AddToDb(MyEntity ent) { ... };

Now, this method could return an entity from Db by reading it, but I don't like making another network request (there's no concurrency in this case). So I'd better assign new Id to the passed entity. But the Id is read-only. I'm thinking to make Persistence layer "friendly" to Domain layer by using InternalsVisibleTo attribute.

Well, it seems a bit hacky and I know the db should be the source of truth. Are there any other options? Am I doing something completely unnecessary/wrong?

Couple of possible options here that spring to mind outside of using InternalsVisibleTo are:

  1. You could make use of the init accessor introduced in C#9 to do what you need?

    public int Id { get; init; }

This would allow you to maintain the property as readonly but you could assign it at object intialisation.

  1. Follow a more CQRS approach and have a "separate data persistance model" and "data view models" and omit the id property from the "create new object view model", make the id property in the persistance model settable (or as previously mentioned initable) and then return the id from the persistance layer before actually committing to the database:

In the externally facing project (view or API or whatever)

public MyEntityViewModel()
{ 
  string SomeProperty { get; set;}
}

Then in the persistance layer

public MyEntity()
{ 
   public int Id { get; init; }
   string SomeProperty { get; set;}
}

public async Task<int> AddToDb(MyEntityViewModel ent) 
{
   var newEnt = new MyEntity(){ Id = 1234 };
   
   //map the contents of the ViewModel to the peristance Model
   newEnt.SomeProperty = ent.SomeProperty;

   ///code to commit to DB.

   return newEnt.Id;
};

Theres all sorts of discusions could be had here about where each model would live, which assembly should have reponsibilty for the mapping etc but I hope this communicates the general idea.

  1. Make the Id property settable and then simply override it within the public async Task AddToDb(MyEntity ent) with a value determined by the persistance layer. This is arguably the simplest option that allows your persistance layer ultimate control while not having to do a lot of laborious logic.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM