We have an application which stores its data in two different databases. At some point in the future we may only be storing our data in one database, so we want it to be as painful as possible to make this kind of change. For this reason, we wrap our DbContexts in a single MyDataContext which gets injected into our UnitOfWork and Repository classes.
class MyDataContext : IDataContext {
internal Database1Context Database1;
internal Database2Context Database2;
}
class UnitOfWork : IUnitOfWork {
MyDataContext myDataContext;
public UnitOfWork(MyDataContext myDataContext) {
this.myDataContext = myDataContext;
}
public Save() {
//todo: add transaction/commit/rollback logic
this.myDataContext.Database1.SaveChanges();
this.myDataContext.Database2.SaveChanges();
}
}
class Database1Context : DbContext {
public DbSet<Customer> Customers { get; set; }
}
class Database2Context : DbContext {
public DbSet<Customers> CustomerProfile { get; set; }
}
class CustomerRepository : ICustomerRepository {
MyDataContext myDataContext;
public CustomerRepository(MyDataContext myDataContext) {
this.myDataContext = myDataContext;
}
public GetCustomerById(int id) {
return this.myDataContext.Database1.Customers.Single(...);
}
}
My first question is, am I doing it right? I've been doing a lot of reading, but admittedly DDD is a little bit overwhelming at this point.
My second question is which layer of the application do the IUnitOfWork and IDataContext interfaces reside in? I know that the interfaces for repositories live in the Core/Domain layer/assembly of the application, but not sure about these two. Should these two even have interfaces?
My first question is, am I doing it right?
You can do that, but first reconsider why you're storing data in different places in the first place. Are distinct aggregates at play? Furthermore, if you wish to commit changes to two different databases within a transaction, you will need to use 2-phase commit which is best to avoid. If you have different aggregates, perhaps you can save them separately?
My second question is which layer of the application do the
IUnitOfWork and IDataContext interfaces reside in?
These can be placed in the application layer.
Related
i'm stuck with this problem while designing aggregates in a DDD project.
Please consider the following scenario:
public abstract class BaseAppType{
public abstract int GetUserOwnerId();
public List<AppTypeHost> Hosts {get;set;} = new List<AppTypeHost>()
}
public class PersonalAppType:BaseAppType //this is an aggregate root
{
public int override GetUserOwnerId(){ return Hosts.Select(h=>h.UserId).Single(); }
}
public class TeamAppType:BaseAppType //this is another aggregate root
{
publi int TeamOwnerId {get;set;}
public int override GetUserOwnerId(){ //this is much harder becase i don't have the info in the object }
}
public class Team {
public List<TeamMember> TeamMembers = new List<TeamMember>();
}
public class TeamMember {
public int TeamId {get;set;}
public int UserId {get;set;}
public TeamMemberRole Role {get;set;} //this might be either Owner or Member
}
So basically i've two types of appointments that share common info, functionality and shape via a root class.
Now i've to implement GetUserOwnerId in the two derived class, which are two distinct aggregates root.
In the PersonalAppType it is kind of easy because the information of the userOwner is within one of the entity of the aggregate so i simply query the object in memory and return it.
In the TeamAppType it is more diffuclt because the information is in another aggregate root ( basically for my business rules, the owner of the TeamAppType is the Owner of the Team AggregateRoot).
Since Team is another AggregateRoot i could not load it into the TeamAppType aggregate and i pretty stuck...
I've tried:
the route of injecting a service in the TeamAppType
so that i can call it within the GetUserOwnerId but i don't like it because it feel "wrong" to inject a service within a domain constructor and it is kind of hard because when i retrieve the aggregate root from ef core, it doesn't inject the service ( because it uses the default construcor with 0 params )
I've also tried the route of doing it in a domain service, something like this:
public class AppTypeOwnerResolverService{
public int GetUserOwnerId (BaseAppType appType)
{
switch (appType.GetType())
{
case "PersonalAppType":
//retrieve owener of PersonalAppType
break
case "TeamAppType":
//retrieve owener of TeamAppType
break
}
}
}
but it feels off because it looks like the GetUserOwnerId should stay within the inherited class and this reduces the benefits of polymorfism.
Do you have any suggestion on how to approach this problem?
Thanks to everyone for the help.
Another option would be to have a Team aggregate emitting domain events, (i.e. TeamOwnerAssigned) and having a domain event handler that modifies the TeamAppType aggregate based on this event.
I am learning DDD and just faced a problem that I can't solve.
Assume we have following domain:
public class Hotel : AggregateRoot {
public List<Room> Rooms { get; private set; }
}
public class Room : Entity {
public string Name { get; set; }
public int Number { get; set; }
}
and now we want to model RoomReservations.
public class RoomReservationRecord : Aggregate {
public string CustomerName { get; set; }
public Room Room { get; set; } // <- this is problem
public DateTime DateFrom { get; set; }
public DateTime DateTo { get; set; }
}
as clearly visible, 2 aggregates contains (share) single entity. It makes sense from business perspective, however from DDD perspective, it looks like 2 aggregates share the same entity.
Is this approach correct, or it violates "Entity can be part of single Aggregate" rule?
Or is there better (obvious way) to model such requirement?
I will try to point out a few things but at the end of the day this is a modeling exercise and often there are compromises to be made.
Invariants - A big part (probably the primary) of why you would group objects in an object graph is to make sure that certain rules are enforced. So if it was a business rule that NO ROOM CAN EVER BE DOUBLE BOOKED, then Hotel would probably be an aggregate root with rooms and reservations as entities on it.
Something like this... but this has some drawbacks...
EG.
class Hotel
{
//members (eg. Rooms and Reservations) ...
public Hotel(string name, ICollection<Room> rooms)
{
//...
}
bool TryMakeReservation(Reservation reservation)
{
// if booked already return false
return true;
}
}
class Room
{
//members ...
public Room(int number, bool isBooked)
{
//..
}
}
class Reservation {
public string CustomerName { get; private set; }
public int RoomNumber { get; private set; }
public DateTime DateFrom { get; private set; }
public DateTime DateTo { get; private set; }
Reservation(Parameters)
{
// ...
}
}
NOTE: To use this model you would need to lock the hotel down each time you make a booking!
This might not be acceptable for a busy hotel. There are ways around this like reserving it for 5 minutes before automatically releasing it unless a reservation is confirmed. Or storing a list of events and if 2 reservations for the same room exist over the same period without a checkout event, kick off a process to notify someone to deal with the double booking.
Contexts - it might be that the list of rooms and the actual bookings are in separate domains. Think about how often bookings are done from multiple sources like AirBnb, Booking.com, hotel website, and/or at the counter in person or over the phone. It might not make sense for bookings and the persistence of available rooms to be in the same domain. What about cleaning schedules. A room needs to be cleaned before it is available but is this really handled in the Booking context?
Performance - as mentioned, sometimes the model we want just isn't possible because of the physics of getting that amount of data queried from a datastore. Users, Product Owners et.c tend not to care how clean your model is if it affects performance too much.
Repositories - following on from the above point, since an aggregate should be a consistent type (ie. data in it should never be in an incorrect state) then when you fetch your aggregate it should be consistent. If Hotel has a repository but contains a room, and Room is an aggregate root and has its own repository, and repositories are calling repositories, I would say you are failing at scaling complexity. The main point of DDD is giving a set of patterns and practices that help you deal with complexity. If by applying DDD principles you increased the complexity by a step that is never capitalized by the future smaller steps in complexity as new features are added, then DDD was probably not the right tool to use at that point in the project.
To speak to the linked article on Ids. Just not using primitive types can mitigate a lot of the problems here. Focusing on finding Value Objects can give a lot of clarity and really help express your domain. Even if you don't use DDD it is a valuable practice, which is why I wrote a series on them without ever mentioning Value Objects... I think.
I hope this helped. DDD, more than even FP to me I guess, has so many super valuable ideas in it that help create maintainable code that scales to requirements. Better than that it has a focus on soft elements outside the code like collaboration and shared a language that brings even more value but they are just guidelines that need to be applied because you want a certain gain (and are willing to pay any incurred costs). They are not rules to apply and very seldom is it just a wrong and right path.
Consider we have a BankCard Entity that is a part of Client Aggregate. Client may want to cancel her BankCard
class CancellBankCardCommandHandler
{
public function Execute(CancelBankCardCommand $command)
{
$client = $this->_repository->get($command->clienId);
$bankCard = $client->getBankCard($command->bankCardId);
$bankCard->clientCancelsBankCard();
$this->_repository->add($client);
}
}
class BankCard implements Entity
{
// constructor and some other methods ...
public function clientCancelsBankCard()
{
$this->apply(new BankCardWasCancelled($this->id);
}
}
class Client implements AggregateRoot
{
protected $_bankCards;
public function getBankCard($bankCardId)
{
if (!array_key_exists($bankCardId, $this->_bankCards) {
throw new DomainException('Bank card is not found!');
}
return $this->_bankCard[$bankCardId]);
}
}
Finally we have some domain repository instance which is reponsible for storing Aggregates.
class ClientRepository implements DomainRepository
{
// methods omitted
public function add($clientAggregate)
{
// here we somehow need to store BankCardWasCancelled event
// which is a part of BankCard Entity
}
}
My question is whether AggregateRoot responsible for tracking its Entities' events or not. Is it possible to get events of an Entity which is a part of an Aggregate from within its Aggregate or not?
How to actually persist the Client with all changes made to the bank card saving its consistency?
I would say the aggregate as a whole is responsible for tracking the changes that happened to it. Mechanically, that could be "distributed" among the aggregate root entity and any other entities within the aggregate or the aggregate root entity as the sole recorder or some external unit of work. Your choice, really. Don't get too hung up on the mechanics. Different languages/paradigms, different ways of implementing all this. If something happens to a child entity, just consider it a change part of the aggregate and record accordingly.
I need to set an event handler on objects that get instantiated by OrmLite, and can't figure out a good way to do it short of visiting every Get method in a repo (which obviously is not a good way).
To give some background - say I have a class User, which is pulled from database; it also implements INotifyPropertyChanged. I want to assign a handler to that event. Having it auto-populated from Funq would be ideal, but of course OrmLite doesn't ask Funq to hydrate the new object.
So I'm stuck.
Any hints in a right direction would be appreciated.
It sounds to me like you're mixing in presentation logic with your data access logic. If I was in your position I would not attempt to implement INotifyPropertyChanged on a model (such as your User class). Instead I would create a ViewModel and place the databinding logic there (MVVM Style).
Having INotifyPropertyChanged on the data model is not quite logical when you get down to it. If I were to update the database record it would not fire this event for example (but the property has changed). It makes a lot more sense on a ViewModel.
Beyond solving your original issue it also makes building complex screens a lot easier by letting you aggregate, compose, and filter data for display purposes. If you need to pull in information from your database, a RSS feed, a stock ticker web API, and twitter you can do so in your ViewModel.
public class User
{
[AutoIncrement]
public int Id { get; set; }
public string Name { get; set; }
}
public class UserViewModel : INotifyPropertyChanged
{
private string _name;
public UserViewModel(User user)
{
_name = user.Name;
}
public string Name
{
get { return _name; }
set {
if (value == _name) return;
_name = value;
OnPropertyChanged("Name");
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Small Note: This answer was written in the context of display data on a screen with a ViewModel, however, the same concept applies to observing model changes for any purpose.
If I have an entity Entity and a service EntityService and EntityServiceFacade with the following interfaces:
interface EntityService {
Entity getEntity(Long id);
}
interface EntityServiceFacade {
EntityDTO getEntity(Long id);
}
I can easily secure the read access to an entity by controlling access to the getEntity method at the service level. But once the facade has a reference to an entity, how can I control write access to it? If I have a saveEntity method and control access at the service (not facade) level like this (with Spring security annotations here):
class EntityServiceImpl implements EntityService {
...
#PreAuthorize("hasPermission(#entity, 'write')")
public void saveEntity(Entity entity) {
repository.store(entity);
}
}
class EntityServiceFacadeImpl implements EntityServiceFacade {
...
#Transactional
public void saveEntity(EntityDTO dto) {
Entity entity = service.getEntity(dto.id);
entity.setName(dto.name);
service.save(entity);
}
}
The problem here is that the access control check happens already after I have changed the name of the entity, so that does not suffice.
How do you guys do it? Do you secure the domain object methods instead?
Thanks
Edit:
If you secure your domain objects, for example with annotations like:
#PreAuthorize("hasPermission(this, 'write')")
public void setName(String name) { this.name = name; }
Am I then breaking the domain model (according to DDD?)
Edit2
I found a thesis on the subject. The conclusion of that thesis says that a good way IS to annotate the domain object methods to secure them. Any thoughts on this?
I wouldn't worry about securing individual entity methods or properties from being modified.
Preventing a user from changing an entity in memory is not always necessary if you can control persistence.
The big gotcha here is UX, you want to inform a user as early as possible that she will probably be unable to persist changes made to that entity. The decision you will need to make is whether it is acceptable to delay the security check until persistence time or if you need to inform a user before (e.g. by deactivating UI elements).
If Entity is an interface, can't you just membrane it?
So if Entity looks like this:
interface Entity {
int getFoo();
void setFoo(int newFoo);
}
create a membrane like
final class ReadOnlyEntity implements Entity {
private final Entity underlying;
ReadOnlyEntity(Entity underlying) { this.underlying = underlying; }
public int getFoo() { return underlying.getFoo(); } // Read methods work
// But deny mutators.
public void setFoo(int newFoo) { throw new UnsupportedOperationException(); }
}
If you annotate read methods, you can use Proxy classes to automatically create membranes that cross multiple classes (so that a get method on a readonly Entity that returns an EntityPart returns a readonly EntityPart).
See deep attenuation in http://en.wikipedia.org/wiki/Object-capability_model for more details on this approach.