We have identified a Location entity in a database as a value object in our domain (DDD). Locations are used by other domain objects, but don't really "stand alone" -- they always belong to another entity.
Now we are trying to edit a list of these values in a simple MVC web application. So the view would show a list of locations in a view model LocationViewModel.
However, the value object is by definition immutable, yet does hold a reference to another entity (Business).
Domain:
public class Location : ValueObject<Location>
{
readonly locationId;
public int LocationId {get{return _locationId;}}
public Business Business {get;set;}
}
My problem is understanding how you can simply edit a bunch of value objects in a UI and change, e.g. what Business the location belongs to.
A value object is not supposed to have an "identity", but it does need an ID so the repository can update the database.
I also don't think you can make Location an entity just because you want to edit it in the UI. Or is Location, in this scenario indeed an Entity?
What am I not understanding?
Thank you!
It's a classic problem. In one context it's an entity and in another a value object. I found the example of a telephone number helpful to understanding this sort of problem.
In a CRM for example, a telephone number is a value object. The same one can be associated with multiple contacts. It varies by value (key concept here). So in this context it's a value object. In this example, I could store telephone numbers in the database and the 'ID' would be the telephone number itself. If the value object was made up of multiple parts then they would form a composite key.
If however we looked at a telephone number at a telephone company. That would most likely be an Entity. It could have all manor of information attached to it. All that info would vary by ID (which in this case would be the number).
In your case, Location sounds like a value object. If you need to save it in a database as a thing rather than just as part of an entity then use it's parts as a composite key. You will need to handle what happens when you 'change' one as it's not a change but the creation of new value object. One approach is to remove the old and insert the new. Or just keep all versions. It depends on your domain.
Hope that's helpful.
You don't change a value object. You create a new one with different values. If the value object has few properties that you want often to change, some helper methods are usefull. myObject.WithX(4711) will create a new instance with all properties the same as myObject but the X Property changed to 4711 for example.
To "edit" a value object in an UI you use a viewmodel. The Viewmodel is not a value object (and no entity by the way) and is not part of your domain. It's purely in the Presentation Layer. It is editable and mutable. It could have a constructor, taking your (immutable) value object to copy its values from and it could have a ToXXX Method to create a new (immutable) value object with its current (and changed) values.
If you want to store your value objects in a separate table (instead of roll out the fields in the table that stores the owning entity) this is purely data access layer related and not part of your domain model. This could be done by mapping. In the value object the database id is immutable and has no meaning in the domain model.
Related
I'm new to Core Data and I got stuck at this part of my xCode project.
I have created a core data entity "Person" and this entity has the following attributes:
name;
age;
birthday;
address;
and this attributes are getting displayed in a tableview. So far so good.
My problem is that I want the table to have an "Add Field" or "Add Row" cell so when the user wants to add more information in addition to these already created attributes he just clicks the cell and chooses the field name and type.
For example if he wants the person's "phone number" in the detail view of the table he names the new field "phone number" and chooses its type "number". Then he has an extra field where he can add the person's phone number.
How can I do this in core data? Is there a way for a user to manually add a new attribute to an entity and choosing its format? What is the best approach? Thanks.
You can't do exactly what you want with Core Data. Core Data can't change structure except if you make a new version of your design, but you do that in xcode.
But you can easily add another table called f.ex. information, which links to the person single connection and has the person linking back many to the information table.
This way, you can add as many fields and values as you want, of course all the extra fields you add would follow the same person, so if you want to use cellPhone field, you must add that to all.
I would recommend that you use direct SQL, and don't use Core Data. Core Data is not a database, it is an object store, and when you get better at iOS development, you will understand the difference, it is much bigger than you might think at first.
There is an excellent high level library for SQLite, called FMDB, you can find it on github here : https://github.com/ccgus/fmdb
Here you can do direct SQL queries like "Alter Table" and more on the fly, though what you are after isn't very simple, it could be real fun project to do.
Good luck with this.
I don't think this is directly possible in Core Data because its purpose is object persistence and you can't add new properties to objects dynamically. It could be faked to some degree using a to-many relationship to an "extra property" entity that had name, value (as string), and data type fields.
I believe your best option would be using SQLite in order to modify the table structure on the fly. (http://www.sqlite.org/lang_altertable.html)
My last company did something like this, but its not trivial. I don't have access to the code so this is more or less going to be from memory.
you provide transformable property in your entity (which will be a dictionary)
the model object has to provide the getter and setter for this that in turn drive the primitive methods to set/get an attribute
you provide a getter/setter along the lines of -objectForKey and -setObject forKey, which read and write values
when you are told to 'fault', you update the dictionary in the entity
In summary, maintain a dictionary of key value pairs. Perhaps you maintain a shadow dictionary that gets initialized and updated as needed. Its been around 4 years since I last saw this code so a little fuzzy on it. But you should get the idea. It was like magic - you can arbitrarily set any key/value pair (assuming string keys and NSCoding compliant values), and can always ask for the keys by asking the dictionary for its current set of keys.
Lets say I have a view that accepts a Person object.
Has three properties, FirstName, LastName, Age
Now lets say I add another textbox field that's not part of the object.
I don't need the value of the textbox, its just populated with data that's for the user.
When you edit the fields and post the Person to the controller, lets assume there is a validation problem so you return the Person object back with Errors
The problem is now the additional textbox has lost it's value since its not part of the model.
So I made a ViewModel with a string property for that field and a Person property to keep all the values. Seems like there would be a better way to keep the value in the "special" textbox?
You should be able to get that extra field from the posted fields. How do you set it first time, through the ViewBag? You should be able to set it again.
But what exactly is wrong with using a ViewModel? Sooner or later you will have 2 or 3 extra fields, or a Person and an Appointment.
I think that's totally the right way to do it. The viewmodel is the model for the view not the model for your non-UI processing, it contains a Person and extra viewable information. It fits exactly with the concept. Your Person is presumably a (non-view) model and therefore when you have a valid post back, you get the Person to save it's data (or whatever) and the extra viewable information is irrelevant at that point, because you are no longer in a 'View/UI' part of your app.
Make the view strongly typed to your viewmodel and access the Person within it
#model myViewModel
#Model.Person.FirstName
#Model.OtherViewOnlyValue
Go with the viewmodel, so much cleaner than ViewBags/Session/ViewData etc.
There are many times that you might think that you do not need to include a UI mapping to a ViewModel but most of the time you will end up adding the mapping into the ViewModel. I believe that ViewModel should represent everything on your UI screen. Since HTTP is stateless the post form values will play an important role in populating the user interface controls.
Say I have a domain level "Person" class that contains a lot of properties(FirstName, LastName, Age, Address, Telephone, EmailAddress, etc). For the purposes of a view, I only need to pass the Age property. The smaller, the better as the collection is being passed to the client as a JSON string.
What is the best way of managing this?
1) Do I create an anonymous type collection and pass that to the view?
2) Do I create a new "ViewModelPerson" type that only contains the "Age" property.
3) Do I create a new domain "Person" super type and have my Person and ViewModelPerson derive from it (seems a convoluted way of doing things).
Then, whats the best way of persisting these details onto my server (ie passing the age value into a collection of Domain Person objects?
EDIT:
Apologies, I should have said that I'd be returning a collection of Person objects (each with just an Age property).
1) I do not think that is possible, please elaborate
2) Yes! I would call it PersonAgeViewModel though.
3) Very convoluted indeed unless you know that you will derive from Person a lot and are planning to implement TPH or TBT in the database anyway.
If you're interested in only sending the Age (a single age) then don't specify a Model in the view at all. Add the value of the age to the ViewBag.
Check out Hajan's Blog Entry.
Call me pedantic, but I would lean towards creating a ViewModel with a single age property. I'm not sure the ViewBag approach would work unless you're building the JSON in a view. Typically when we return JSON we just use
return Json(model);
I would definitely recommend against a common base type between domain and view models.
This happens in ASP.NET MVC 2, .NET 4 (EF 4). My Address entity has a reference to the Post reference. Zip is the primary key of the Post entity. Another property in Post entity is CityName. In my views I allow users to change the CityName for the address which automatically (via jquery) loads up the corresponding Zip and stores it inside a hidden field.
When posted, both values are posted fine and binded to the Address's Post reference. But UpdateModel() fails to update them. It says that the Zip is part of the entity's Entity Key and cannot be changed.
I would gladly load up the Post entity by the new Zip and manually assign it to the existing Address but for all other properties I stall want to rely on UpdateModel().
How can I achieve that? One would think that in EF4 stuff like this has been resolved..
By default the entity framework generated classes put restrictions on changing primary key values. This is good. You shouldn't change a PK for any reason at all. Changing PKs outside of add scenarios has pretty huge ramifications for state tracking and the general health of your system.
To solve this problem you want to tell UpdateModel not to update your primary keys using the exclude parameter.
My current setup:
I have an entity object with some properties, among them an int Id. To communicate with the database, I've created a repository with, among others, the following method:
public int Add(TEntity entity)
{
ObjectSet.AddObject(entity);
return entity.Id;
}
(It's a generic repository, that requires that TEntity is a class, and that it implements IEntity, which is just an interface with an int Id property.)
My problem:
Now, when I want to create a new entity for adding to the repository, I need to give it an id. However, that doesn't allow EF to automatically generate the id for me, since it will already have a value.
Possible solutions:
I have only been able to think of these two possibilities.
Make the Id property nullable
Pass an EntryInputModel to the repository instead, and then do the mapping there.
Currently I'm binding to EntryInputModel in my Controller, and mapping it to an Entry using AutoMapper. If I need to change this, I also need to re-think the dependencies in my project, since the ...InputModel and ...ViewModel classes are currently only available to my Web application.
Which is preferable? Are there more ways to counter this?
If you're using SQL Server as the backend, my recommended solution would be to make the ID column an INT IDENTITY on the database, and a not-nullable column in your entity object.
When adding a new entity, assign the ID some arbitrary value, like -1 or something, or no value at all, even. The actual ID will be generated automatically by SQL Server when you insert the new entity (
EntityContext.AddToEntities(newEntity);
EntityContext.SaveChanges();
and it will be automagically be signalled back to EF so you'll be able to use it right away once it's inserted:
int newEntityID = newEntity.ID;
Works like a charm - at least in my test apps :-)
you can have generated unique id's that are not generated by the datastore/EF, allowing you to define them before passing the object into EF... (think of Guid's)