I have a two aggregate roots in my domain, and therefore two repositories. We'll call them BookRepository, and AuthorRepository, for the sake of example.
I'm designing an MVC application, and one page has to display a table containing a list of authors, with each row showing the author's personal details. At the end of each row is a small button that can be clicked to expand the row and show a child table detailing the author's published books.
When the page loads, some ajax is executed to retrieve the Author details from an API controller and display the data in the table. Each property in an Author object maps almost directly to a column, with one exception, and this is where I'm having my problem. I want the button at the end of each row to be disabled, if and only if the author has no published books. This means that a boolean has to returned with each Author record, indicating if they have any published books.
My book repository has a couple of methods like this:
public IEnumerable<Book> GetBooksForAuthor(int authorId);
public bool AnyBooksForAuthor(int authorId);
and my Book class has a property called AuthorId, so I can retrieve a book's author by calling
authorRepository.GetById(book.AuthorId);
My problem is that in order to create a row for my aforementioned table, I need to create it like this:
IEnumerable<Author> authors = authorRepository.GetAll();
foreach (Author author in authors)
{
yield return new AuthorTableRow
{
Name = author.Name,
Age = author.Age,
Location = author.PlaceOfResidence.Name,
HasBooks = this.bookRepository.AnyBooksForAuthor(author.Id)
};
}
The above code seems correct, but there's a fairly heft performance penalty in calling this.bookRepository.AnyBooksForAuthor(author.Id) for every single author, because it performs a database call each time.
Ideally, I suppose I would want an AuthorTableRowRepository which could perform something like the following:
public IEnumerable<AuthorTableRow> GetAll()
{
return from a in this.dbContext.Authors
select new AuthorTableRow
{
Name = a.Name,
Age = a.Age,
Location a.PlaceOfResidence.Name
HasBooks = a.Books.Any()
});
}
I'm hesitant to put this in place for these reasons :
AuthorTableRowRepository is a repository of AuthorTableRows, but AuthorTable row is not a domain object, nor an aggregate root, and therefore should not have its own repository.
As Author and Book are both aggregate roots, I removed the "Books" property from the Author entity, because I wanted the only way to retrieve books to be via the BookRepository. This makes HasBooks = a.Books.Any() impossible. I am unsure whether I am imposing my own misguided best practice here though. It seems wrong to obtain Books by obtaining an Author via the AuthorRepository and then going through its Books property, and vice versa in obtaining an Author via a property on a Book object. Crossing aggregate root boundaries would be the way I'd term it, I suppose?
How would other people solve this? Are my concerns unfounded? I am mostly concerned about the (what should be a) performance hit in the first method, but I want to adhere to best practice with the Repository pattern and DDD.
I would stick to the first approach, but try to optimize things in the bookrepository method. For instance, you can load this information all in one time, and use in-memory lookup to speed this up. Like this you would need 2 queries, and not 1 for each author.
The way I solved this in the end was to create an Entity from a view in the database. I named the entity 'AuthorSummary', and made an AuthorSummaryRepository that didn't contain any Add() methods, just retrieval methods.
Related
I've recently started looking into DDD and have been refactoring an old personal project to this pattern. I'm about halfway through Evans blue book, and can't seem to find the answer for this there or online anywhere.
Basically my application is an inventory tracker. Inventory would contain a collection of items, items are transferrable entities between inventories. Inventory would have methods like transferIn() transferOut() which would contain some validation logic, ie checking that the inventory is not already full or that the item is in a transferrable state. These constraints lead me to believe that inventory is the aggregate root and that item is an entity.
1) at some point if a user requests a specific item entity for their inventory I would like to have a inventoryRepo.findByItemId(id) which would return the inventory that currently has that item. So that I can:
2) through a service do something like:
boolean requestItemTransfer(destInvId, itemId){
Inv from = invRepo.findByItemId(itemId);
Inv to = invRepo.findById(destInvId);
from.transferOut(itemId);
to.transferIn(from.getItem(itemId));
return invRepo.transferChild(to, item); //Edited
}
Basically writing my validation logic in the inventory class (rich domain model) and if there are no exceptions then I use the repo.transfer() method to persist the changes.
Would I be violating DDD? Are there better alternatives?
From what I've read and understood this seems valid if only unconventional. Every example that I've found shows entities that can only exist within 1 root instance. There's also the bank account transfer examples but those deal with amounts that are value objects, and have a transfer repository because transfers are to be recorded in that particular scenario, just not in mine.
EDIT:
The use cases are as follow:
1) User requests a list of their inventories and their items.
2) User selects 1 or more items from 1 inventory and requests for them to be sent to another inventory. This is where my TransferService would come in and coordinate the txIn and txOut from the specified inventories, and persist those changes through the repo. Maybe that should be an infrastructure services? That's one thing I'm not clear on.
3) User predefines a set of items he would like to be able to transfer to an inventory regardles of what inventory those items are currently in. TransferService would find where those items currently are and coordinate the rest as use case 2 does.
EDIT2: About the repo.transfer
This is actually a constraint/optimization? from the data side, from what I've been told all it does is lookup the item and change the inventory id that it points to. This is because items cannot be in 2 inventories at once. So instead of repo.update(fromInvInNewState) and repo.update(toInvInNewState) there is repo.moveChild(toInv, child) because we don't want to rewrite the entire state of the inventory (all its items that haven't moved, and because the rest of its state is derived from the items that it has at any point), just move some items around.
You are missing at least one aggregate and trying to replace it with your persistence. Talk to your domain expert, find out who or what is doing this transfer. I bet you will not hear that this is done by "a repository" or "a database". This something will be your aggregate and it will probably have this Transfer method. This call would also encapsulate the login from transferIn and transferOut since this seems to be a transactional process and you are doing it in three different places. Remember that your transaction boundaries is your aggregate. Not your repository.
First of all I would like to recap the domain model defined by your scenario.
You said that you are building an Inventory Tracker with the next spec:
An User has Inventories.
An Iventory consists of Items.
An User can transfer Items from one Inventory to another. I guess that both inventories belong to the User as you said that:
"User requests a list of their inventories and their items. User selects 1 or more items from 1 inventory and requests for them to be sent to another inventory..."
On the other hand, an invariant you pointed out are:
An Item can be transferred from the Inventory where it already is (InventoryA) to another Inventory (InventoryB) only if InventoryB is not already full. I guess that in case that the Item cannot be transferred it should be kept in the InventoryA.
If I understood well, an User transfers his Items between his Repositories.
Something like:
class TransferItemService {
public function execute(TransferItemRequest request)
{
user = userRepository.findOfId(request.userId());
user.transferItem(request.itemId(), request.fromInventoryId(), request.toInventoryId()); //Checks invariant -> the given Item is in one of his Inventories, the destination Inventory is owned by him, the destination Inventory is not full and finally transfers the Item
userRepository.save(user);
}
}
Now, in order to define the Aggregate Root/s I would need to know if my business can deal with eventual consistency. That is, if moving an Item must be done atomically (just one request) or it can take some time (more than one request).
No Eventual Consistency
In case business says that Eventual Consistency is not allowed here, if you want to ensure that your domain remains consistent and aligned to the invariant, the User would be the unique AggregateRoot as he is the nexus between his Inventories. In this case, you can face performance problems due to loading all the Inventories along with their Items.
Eventual Consistency
In case that you can go with eventual consitency, you can have the next Aggregate Roots: User, Inventory, Item. So, using the previous code to model the use case of transferring an item:
class TransferItemService {
public function execute(TransferItemRequest request)
{
user = userRepository.findOfId(request.userId());
user.transferItem(request.itemId(), request.fromInventoryId(), request.toInventoryId()); //Checks invariant -> the given Item is in one of his Inventories, the destination Inventory is owned by him, the destination Inventory is not full and finally transfers the Item
userRepository.save(user);
}
}
In this case, the transferItem method would look like:
class User {
private string id;
private List<UserInventory> inventories;
public function transferItem(itemId, fromInventoryId, toInventoryId)
{
fromUserInventory = this.inventories.get(fromInventoryId);
if(!fromUserInventory) throw new InventoryNotBelongToUser(fromInventoryId, this.id);
toUserInventory = this.inventories.get(toInventoryId);
if(!toUserInventory) throw new InventoryNotBelongToUser(toInventoryId, this.id);
toUserInventory.addItem(itemId);
fromUserInventory.deletetItem(itemId);
}
}
class UserInventory {
private String identifier;
private int capacity;
public function deleteItem(userId, itemId)
{
this.capacity--;
DomainEventPublisher.publish(new ItemWasDeleted(this.identifier, itemId));
}
public function addItem(userId, itemId)
{
if(this.capacity >= MAX_CAPACITY) {
throw new InventoryCapacityAlreadyFull(this.identifier);
}
this.capacity++;
DomainEventPublisher.publish(new ItemWasAdded(this.identifier, itemId));
}
}
Notice that UserInventory is not the Inventory Aggregate Root, it is just a VO with an identifier reference and the current capacity of the actual Inventory.
Now, you can have a Listener that asynchonously updates each Inventory:
class ItemWasRemovedListener()
{
public function handleEvent(event)
{
removeItemFromInventoryService.execute(event.inventoryId(), event.itemId());
}
}
class ItemWasAddedListener()
{
public function handleEvent(event)
{
addItemToInventoryService.execute(event.inventoryId(), event.itemId());
}
}
Unless I have made a mistake I think we have satisfied all our invariant, we have just modified one Aggregate Root per Request and we don't need to load all our Items to perform an operation on an Inventory.
If you see something wrong please let me know :D.
(as advised re-posting this question here... originally posted in msdn forum)
I am striving to write a "generic" routine for some simple CRUD operations using EF/Linq to Entities. I'm working in ASP.NET (C# or VB).
I have looked at:
Getting a reference to a dynamically selected table with "GetObjectByKey" (But I don't want anything from cache. I want data from database. Seems like not what this function is intended for).
CRM Dynamic Entities (here you can pass a tablename string to query) looked like the approach I am looking for but I don't get the idea that this CRM effort is necessarily staying current (?) and/or has much assurance for the future??
I looked at various ways of drilling thru Namespaces/Objects to get to where I could pass a TableName parameter into the oft used query syntax var query = (from c in context.C_Contacts select c); (for example) where somehow I could swap out the "C_Contacts" TEntity depending on which table I want to work with. But not finding a way to do this ??
Slightly over-simplyfing, I just want to be able to pass a tablename parameter and in some cases some associated fieldnames and values (perhaps in a generic object?) to my routine and then let that routine dynamically plug into LINQ to Entity data context/model and do some standard "select all" operations for parameter table or do a delete to parameter table based on a generic record id. I'm trying to avoid calling the various different automatically generated L2E methods based on tablename etc...instead just trying to drill into the data context and ultimately the L2E query syntax for dynamically passed table/field names.
Has anyone found any successful/efficient approaches for doing this? Any ideas, links, examples?
The DbContext object has a generic Set() method. This will give you
from c in context.Set<Contact>() select c
Here's method when starting from a string:
public void Test()
{
dynamic entity = null;
Type type = Type.GetType("Contract");
entity = Activator.CreateInstance(type);
ProcessType(entity);
}
public void ProcessType<TEntity>(TEntity instance)
where TEntity : class
{
var result =
from item in this.Set<TEntity>()
select item;
//do stuff with the result
//passing back to the caller can get more complicated
//but passing it on will be fine ...
}
I have a form which has several unique fields for that form say, School, class,
Location etc and several fields that needs to be repeated say, , Student id, Student name, Student roll no.
I want to repeat the last three fields 10 times.
Secondly, how do I store it in database (MySQL using doctrine). I mean rows should be created depending on the number of last three fields and the first three fields should remain same.
How do I achieve this in a Symfony2?
Any help will be highly appreciated.
The form structure is something like this:
School Class Location
Sno Student id Student Name Student Roll No
1.2.3.4.5.And so on......Edit: Fixed at 10 rows
Update
Entity Class:
class StudentForm
{
private $id;
private $school;
private $class;
private $location;
private $id;
private $name;
private $rollNo;
getter/setter methods follow
Well. Up to now I always used the JavaScript provided in the example. You could try to call this function 10 times, or see how the markup is created. But then again this will probably not work with the code in the controller from the example.
You can always create the whole markup yourself and then just see who that data is received in your controller. But then again, there wasn't too much information in your initial description. It seemed you currently don't have the code for your entities.
After a good long process of trial and error, I finally managed to do it.
The doctrine documentation helped creating a collection (though it didn't give enough information on saving the objects) for the repeating rows and so did the inputs of #Dirk Olbertz here. Thank you.
I have a common Repository with Add, Update, Delete.
We'll name it CustomerRepository.
I have a entity (POCO) named Customer, which is an aggregate root, with Addresses.
public class Customer
{
public Address Addresses { get; set; }
}
I am in a detached entity framework 5 scenario.
Now, let's say that after getting the customer, I choose to delete a client address.
I submit the Customer aggregate root to the repository, by the Update method.
How can I save the modifications made on the addresses ?
If the address id is 0, I can suppose that the address is new.
For the rest of the address, I can chose to attach all the addresses, and mark it as updated no matter what.
For deleted addresses I can see no workaround...
We could say this solution is incomplete and inefficient.
So how the updates of aggregate root childs should be done ?
Do I have to complete the CustomerRepository with methods like AddAddress, UpdateAddress, DeleteAddress ?
It seems like it would kind of break the pattern though...
Do I put a Persistence state on each POCO:
public enum PersistanceState
{
Unchanged,
New,
Updated,
Deleted
}
And then have only one method in my CustomerRepository, Save ?
In this case it seems that I am reinventing the Entity "Non-POCO" objects, and adding data access related attribute to a business object...
First, you should keep your repository with Add, Update, and Delete methods, although I personally prefer Add, indexer set, and Remove so that the repository looks like an in memory collection to the application code.
Secondly, the repository should be responsible for tracking persistence states. I don't even clutter up my domain objects with
object ID { get; }
like some people do. Instead, my repositories look like this:
public class ConcreteRepository : List<AggregateRootDataModel>, IAggregateRootRepository
The AggregateRootDataModel class is what I use to track the IDs of my in-memory objects as well as track any persistence information. In your case, I would put a property of
List<AddressDataModel> Addresses { get; }
on my CustomerDataModel class which would also hold the Customer domain object as well as the database ID for the customer. Then, when a customer is updated, I would have code like:
public class ConcreteRepository : List<AggregateRootDataModel>, IAggregateRootRepository
{
public Customer this[int index]
{
set
{
//Lookup the data model
AggregateRootDataModel model = (from AggregateRootDataModel dm in this
where dm.Customer == value
select dm).SingleOrDefault();
//Inside the setter for this property, run your comparison
//and mark addresses as needing to be added, updated, or deleted.
model.Customer = value;
SaveModel(model); //Run your EF code to save the model back to the database.
}
}
}
The main caveat with this approach is that your Domain Model must be a reference type and you shouldn't be overriding GetHashCode(). The main reason for this is that when you perform the lookup for the matching data model, the hash code can't be dependent upon the values of any changeable properties because it needs to remain the same even if the application code has modified the values of properties on the instance of the domain model. Using this approach, the application code becomes:
IAggregateRootRepository rep = new ConcreteRepository([arguments that load the repository from the db]);
Customer customer = rep[0]; //or however you choose to select your Customer.
customer.Addresses = newAddresses; //change the addresses
rep[0] = customer;
The easy way is using Self Tracking entities What is the purpose of self tracking entities? (I don't like it, because tracking is different responsability).
The hard way, you take the original collection and you compare :-/
Update relationships when saving changes of EF4 POCO objects
Other way may be, event tracking ?
I have an Open JPA entity and it successfully connects a many-to-many relationship. Right now I successfully get the entire table, but I really only want the ID's from that tables. I plan on calling the database later to reconstruct the entities that I need (according to the flow of my program).
I need only the ID's (or one column from that table).
1) Should I try and restrict this in my entity beans, or in the stateless session beans that I will be using to call the entity beans
2) If I try and do this using JPA, how can I specify that I only get back the ID's from the table, instead of the whole table? So far looking online, I don't see a way that you can do this. So I am guessing there is no way to do this.
3) If I simply just manipulate the return values, should I create a separate class that I will be returning to the user that will return only the required id list to the user?
I could be completely wrong here, but from the looks of it, I don't think there is a simple way to do this using JPA and I will have to return a custom object instead of the entity bean to the user (this custom object would only hold the id's as opposed to the whole table as it currently does)
Any thoughts... I don't think this is really relevant, but people are always asking for code, so here you go...
#ManyToMany(fetch=FetchType.EAGER)
#JoinTable(name="QUICK_LAUNCH_DISTLIST",
joinColumns=#JoinColumn(name="QUICK_LAUNCH_ID"),
inverseJoinColumns=#JoinColumn(name="LIST_ID"))
private List<DistributionList> distributionlistList;
Currently how I get the entire collection of records. Remember I only want the id...
try
{
//int daSize = 0;
//System.out.println("Testing 1.2..3...! ");
qlList = emf.createNamedQuery("getQuickLaunch").getResultList();
}
This is how I call the Entity beans. I am thinking this is where I will have to programatically go through and create a custom object similar to the entity bean (but it just has the ID's and not the whole table, and attempt to put the id's in there somewhere.
What are your thoughts?
Thanks
I believe I just figured out the best solution to this problem.
This link would be the answer:
my other stack overflow answer post
But for the sake of those too lazy to click on the link I essentially used the #ElementCollection attribute...
#ElementCollection(fetch=FetchType.EAGER)
#CollectionTable(name="QUICK_LAUNCH_DISTLIST",joinColumns=#JoinColumn(name="QUICK_LAUNCH_ID"))
#Column(name="LIST_ID")
private List<Long> distListIDs;
That did it.
Sounds like you want something like this in your quickLaunch class:
#Transient
public List<Integer> getDistributionListIds () {
List<Integer> distributionListIds = new LinkedList<Integer>();
List<DistributionList> distributionlistList = getDistributionlistList();
if (distributionlistList != null) {
for (DistributionList distributionList : distributionlistList)
distributionListIds.add(distributionList.getId());
}
return distributionListIds;
}
I had to guess a little at the names of your getters/setters and the type of DistributionList's ID. But basically, JPA is already nicely handling all of the relationships for you, so just take the values you want from the related objects.