I want to use a Money value object in my application. I have found several examples of a Money datatype. But I can't figure out how to use them with EF4. I would like to store each amount as a Decimal/CurrencyCode pair (where currencycode is a string - "USD", "SEK", etc) in the database. I tried creating a complexType but I couldn't get that to work. Is this possible?
It should be definitely possible. Your complex type is just pair of decimal and string property. It is exactly what complex type are used for. Depending on your approach you must do:
Database first:
You will define your database first. Your table will contain money and varchar columns representing your new type. When you update your EDMX model from database it will include it as scalar properties to your entity. You must remove those properties. Then go to model browser and create new complex type. Return back to entity and add complex property of your new complex type. And at the end you must go to entity mapping and map your complex type to those database columns.
Here is basic tutorial from MSDN but from unknown reason they didn't include such elementary details like screenshots. Here is some video from channel9.
Model first:
This is similar to database first but you don't have to deal with database creation and mapping. It will be generated for you.
Code first (EF 4.1):
You must create separate class for your complex type and use it as property in your entity. You should not need to map it by default - mapping should be infered. If it doesn't work you can map complext type either by using ComplextTypeAttribute annotation or by defining mapping in DbModelBuilder.
I can further extend approach you need to use if you provide more details.
Related
I am making a ZF2 app. I am using entities, mappers and services (e.g. UserEntity, UserMapper, UserService) to manage the objects/models. Properties in the entities are CamalCased (e.g. FirstName, LastName) while in the database, fields are using underscore (first_name, last_name). I will plan to use a hydrator to map the properties and db-fields when retrieving or saving. The service object (UserService) will be used to communicate with the mapper to retrieve and save data models using the mapper. The hydrator will convert the result of mapper and convert them into proper entities.
The thing I am confused is that when the service (UserService) need to provide some cirteria - for example to find all users with a specific 'last name', will the service use the database field names (last_name) or entity properties name (LastName)?
If the db field name is used in the Service, so any change in the db structure will require me to update the service also, which completely fails the reason of using the whole approach.
If you take a look at the ClassMethods:hydrate method (https://github.com/zendframework/zf2/blob/master/library/Zend/Stdlib/Hydrator/ClassMethods.php) you will see that it just copies the properties from one object to another. You have the option of converting the property names to/from camelCase but that's it.
If you change a column name in your database then you will need to change corresponding property name in your object. And vice versa. Which I believe is the crux of your question?
If you want to make table column names be independent of your method names then you need something that lets you define an actual mapping table somewhere. Change a column or method name and you only need to update the configuration mapping table.
Not a ZF2 expert so I could be wrong but it doesn't look like any of the supplied hydrators support this.
I do know that Doctrine 2 supports it.
Here is the senario for which I could not find anything useful. Maybe Im the first person thinking of doing it this way:
Approach: Database First
Database: SQL Server 2008 R2
Project : DLL (Data Access)
I have a data access library which encapsulates all the access to database as well as the biz functionality. The database has many tables and all the tables have the following 2 columns:
last_updated_on: smalldatetime
last_updated_by: nvarchar(50)
The project contains several models (or edmx files) which contain only related entities which are mapped to the tables they represent. Since each of the table contain the columns for last_updated_* I created a complex type in one of the models that is as follows:
Complex Type: History
By (string: last_updated_by)
On (DateTime: last_updated_on)
The problem is that it can only be used in the model in which I defined it.
A) If I try to use it in other model it does not show it in the designer
B) If i define it in the other models I get error History already defined
Is there any solution so that the History complex type, defined in one model can be reused by other models?
I was trying to do almost the exact same thing (my DB fields are "created", "creatorId", "modified", and "modifierId", wrapped up into a complex type RecordHistory) and ran into this question before finding an answer...
http://msdn.microsoft.com/en-us/data/jj680147#Mapping outlines the solution, but since it's fairly simple I'll cover the basics here too:
First create the complex type as you did (select the fields in the .edmx Designer, right click, select "Refactor into New Complex Type")
In the .edmx Designer (NOT the Model Browser) right click on another table/entity that has the same common columns and select Add -> Complex Property
The new property will be assigned a complex type automatically. If you have more than 1 complex type, edit the new property's properties and set the Type appropriately
Right-click on the table/entity again (in either the Model Browser or Designer) and select Table Mapping
Update the Value/Property column for each of your common fields (changing them, in my case, from "modified : DateTime" to "history.modified : DateTime")
Delete the old common fields from your entity, leaving just the complex type in their place
I am using EF 4.1, code first and want a property on a customer entity built up of a constant string value and the customerId zero padded to act as a customer reference.
I might be being a bit daft but am struggling to work out how I can achieve this without
A) having to savechanges twice, once to get the Id then set my reference and save again
B) having a partial Customer class that simply provides a getter returning constant + CustomerId.Tostring("000000")
Is this "doable" with code first?
If you can change the database I would make a computed column for this. Thus, you leave it to the database to generate a reference value and it will also be available to other consumers of the database (if any).
Your Customer class will have a property like CustomerReference (string) that maps to the computed column and that is configured to have DatabaseGeneratedOption.Computed which will cause EF to read the value after inserting an object.
When we have two entities in EFv4 EDM diagram and only one table for both in the database (for instance, having table Documents and entities Invoice and Qoute), table Documents having documentTypeId column as a discriminator and set this column as a discriminator in the EDM (in Table mappings), how do we read the value of this property in our code?
We cannot assign values to it because EF does it for us under the hood (based on what we entered in Table mappings for condition) but somehow I don't get it why we are also not allowed to read it.
Imo this property is already mapped so you can't map it again. It is used to determine type of materialized entity. Why do you need such column. Usually it is enough to use is operator like:
var document = context.Documents.GetById(id);
if (document is Invoice)
{
...
}
If you only need to select subtypes you can use OfType extension method like:
var invoices = context.Documents.OfType<Invoice>().ToList();
You also don't need to set this value when adding new entity because you are adding subtype - Invoice or Quote.
Edit:
As I understand from your comment you don't need this information in query. In such case you don't need to map it. Simply use partial class of your entity and add custom property which will return your string. Sound like stupid solution but actually it would be the easiest one.
Discriminator column should be part of mapping metadata so in case of T4 template generating your entities, it could be possible to update the template so it generate such property for you.
You may want to use a single-table inheritance hierarchy, as described here.
That way, you could have an abstract Document class that includes a DocumentTypeId column. Invoices and Quotes would extend this class, but specify certain DocumentTypeId filters. However, because the original class has a DocumentTypeId column, they would each have that column as well.
Another advantage to this approach is that you could create utility methods that can act on any Document, and you could pass any Invoice or Quote to these methods.
We're using a Function Import in an EF4 model to populate an existing entity in our Model. The entity in the model has a Key field of Id which we're struggling to map as our stored procedure doesn't return an Id field. I've tried setting the value in the mapping to a literal value of 0 but that fails with an EntityCommandExecutionException and the following exception text.
The data reader is incompatible with the specified 'Candidate'. A member of the type, 'Id', does not have a corresponding column in the data reader with the same name.
Short of modifying the stored procedure to return a dummy Id field can anyone recommend what the best approach is for this as the dummy field option feels very clunky to me.
Many Thanks
If you can't return enough data to fully materialize the entity -- and the Id field is certainly going to be required for that -- then you need to change the return type on the proc to be a complex type instead of an entity.
Use another POCO class with the same structure to receive the results of the stored procedure call, here's an example:
string sp = string.Format("EXEC dbo.spComercialesAsociadosActivos {0}", idComercialPrincipal);
return ((IObjectContextAdapter)this).ObjectContext.ExecuteStoreQuery<InfoComercial>(sp);
In this case "InfoComercial" is a POCO class with the same structure as "Comercial", which is tied up to EF code first in the DBContext, then I used this independent class in the viewModel to create a disconnected "Comercial", it's not an ideal solution but will work fine until EF 5 comes with SP support.