Entity Framework - Mapping decimal(13,0) problem - entity-framework

I'm migrating the aplication of my company (that nowadays run over SQL Server and Oracle) to ASP NET MVC and Entity Framework for persistence.
A create my Entity Model based on SQL Server Database e separately I create a SSDL for Oracle (for Oracle I use DevArt dotConnect for Oracle Provider) and I get some pain troubles.
My table primary keys are on SQL Server are of type decimal(13,0) and on Oracle are number(13,0) but Oracle map it's type to Int64 and SQL Server to decimal, but I need that SQL Server map it to Int64.
I make these modification manually on Entity Data Model and for create records it's works fine, but when I have to delete or update some record I got these error:
The specified value is not an instance of type 'Edm.Decimal'
Parameter name: value
at System.Data.Common.CommandTrees.DbConstantExpression..ctor(DbCommandTree commandTree, Object value, TypeUsage constantType)
at System.Data.Mapping.Update.Internal.UpdateCompiler.GenerateValueExpression(DbCommandTree commandTree, EdmProperty property, PropagatorResult value)
at System.Data.Mapping.Update.Internal.UpdateCompiler.GenerateEqualityExpression(DbModificationCommandTree commandTree, EdmProperty property, PropagatorResult value)
at System.Data.Mapping.Update.Internal.UpdateCompiler.BuildPredicate(DbModificationCommandTree commandTree, PropagatorResult referenceRow, PropagatorResult current, TableChangeProcessor processor, Boolean& rowMustBeTouched)
at System.Data.Mapping.Update.Internal.UpdateCompiler.BuildDeleteCommand(PropagatorResult oldRow, TableChangeProcessor processor)
at System.Data.Mapping.Update.Internal.TableChangeProcessor.CompileCommands(ChangeNode changeNode, UpdateCompiler compiler)
Someone can help me?
Why Entity Framework mapping are so fixed? It could be more flexible?
Ps.: The error that I got, I suspect that is because of a association.
I have a Entity named Province and another named Country and I think that the association between these Entities are causing the problem at update and delete.
Regards,
Douglas Aguiar

This may or may not help you, but i had the same error from doing this same thing. So I edited the Conceptual model and change the primary key field from Int32 to Decimal. So far, seems to have fixed things. I still need to test again against Sql Server and make sure this didnt break it.

I was getting the error "The specified value is not an instance of type 'Edm.Decimal' Parameter name: value" as you posted in your question. I had changed the default data types from Decimal to Int32 as this better reflects the true typing. When I first hit this error I rolled back the type changes and was still getting an exception but it changed just slightly but led to further digging. Bottom line, in my scenario we were expecting a trigger to populate the PK during persistence via Before Insert directive. The problem was that the domain class built by EF was setting the PK at 0 so the trigger was never firing as the incoming PK was not null. Of course EF will not let you set the Entity PK to be nullable. Maybe this will help someone else in the future.

Related

Why does Entity Framework insist on renaming columns?

Step 1: import code first from existing database. Existing database has a table with the same name as column.
Step 2: in this scenario, Entity Framework sticks a "1" in front of column name in code.
Step 3: when I try to rename it "by getting rid of 1 in front", I get error
member names cannot be the same as their enclosing type
Why is this limitation on EF and is there a solution that doesn't ruin the database in future migrations (by having that column renamed)?
Being forced to use Column1 just seems really terrible and arbitrary.
Thanks.
As pointed out by #shf301 you cant have a property named the same as the class its in, this is a .NET restriction.
However you can name your column anything else and then tell EF to point to your specific column in the database
eg:
[Column("MyColumn")] // "MyColumn" will be what EF expects in the db
public int FlyingMonkies {get;set;}

EF code-first migration: SqlCeException altering NTEXT column

My application uses Entity Framework 5.0 code-first on top of a Sql CE database. Until now, we have used Automatic Migrations to manage entity mapping changes. However, I now have a change for which I need to create a custom migration to ensure no data is lost during the update. I made my changes to the entities, and used the Add-Migration command which generated Up() and Down() methods for me. I customized the Up() method to insert my custom sql to preserve the data, and tested my application.
When I run the application, I received the error:
Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending model changes to a code-based migration or enable automatic migration. Set DbMigrationsConfiguration.AutomaticMigrationsEnabled to true to enable automatic migration.
Ok, I don't understand this because all of my changes are detailed in the Up() method that got executed.
So I turn Automatic Migrations back on just to see what happens. Now I receive this error:
"Cannot alter column of type NTEXT or IMAGE [ Column Name = LastName ]"
This error comes from a table/entity that hasn't even been touched with my changes. The existing database has this string mapped to nvarchar(4000). If I examine the DB after I receive this exception, I observe that the columns have been changed to ntext. What is EF doing? Why is it touching tables that haven't been changed? How can I get more information on what is going on here?
Update:
As a workaround, I attempted to mark each and every string type in my entities with a data annotation as such:
[Column(TypeName = "ntext")]
public virtual string LastName
{
get;
set;
}
Now all of my strings are using ntext in the database. This leads to further exceptions when queries are performed:
The ntext and image data types cannot be used in WHERE, HAVING, GROUP BY, ON, or IN clauses, except when these data types are used with the LIKE or IS NULL predicates.
So, to summarize:
Turning off automatic migrations causes EF to detect phantom changes and throw exceptions
Turning on automatic migration in conjunction with a custom migration causes all existing strings to be mapped to ntext
strings mapped to ntext cannot be queried, effectively making them useless in my application
For me, a modification of an Up method worked out.
SerialNumber = c.String(maxLength: 99)
was applied instead of
SerialNumber = c.String()
i had the same issue and i fixed by editing the table column data type manually by opening SQl Server Compact/SQlite Toolbox explorer windows, and then expend the database name, then expend the table you want to edit and right click the column you want to edit, and click drop script, then run the scrip and the column will be dropped from the table, then right click the table and click add column and from here you can choose what data type you want and add the new column that way. I hope this helps some one.

Entity Framework Cardinality Issue on a 0...1 Association

I have database tables that look like this:
A Task can be mapped to a Module, or not mapped at all (0...1). I'm using Entity Framework database-first, and when I generated the model from the database, the Task entity came through with Modules as a collection (0 or more). So I opened up my EDMX and changed the "Modules" navigation property on Task to 0...1.
Now, when I attempt to compile, I get this error:
Error 3003: Problem in mapping fragments starting at line 1241:Given the cardinality of Association End Member Task, it should be mapped to key columns of the table TaskModule. Either fix the mapping or change the multiplicity of this end.
I don't understand what I need to do to fix this. I've looked at the association details and can't see the issue. I know I'm probably missing something stupid, but am totally stuck. Association properties:
Visual Studio 2010 SP1, Entity Framework 4.3.1.0, SQL Server 2008 R2.
One way to do this is to redefine the primary key for the TaskModule table. Instead of the primary key being (TaskId, ModuleName) it needs to be just (TaskId). Then do an update model from database and change any of the associations manually that didn't get picked up from that update.
Well your database schema is not correct with the description you give :
the TaskModule table implicates a many-to-many relationship, not a many-to-oneOrZero.
In edmx, many-to-many relation tables are not displayed, but they still exist in database.
So you should fix your database, or be happy with the relation proposed by EF !

stored procedure mapping Entity Framework

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.

GUID or int entity key with SQL Compact/EF4?

This is a follow-up to an earlier question I posted on EF4 entity keys with SQL Compact. SQL Compact doesn't allow server-generated identity keys, so I am left with creating my own keys as objects are added to the ObjectContext. My first choice would be an integer key, and the previous answer linked to a blog post that shows an extension method that uses the Max operator with a selector expression to find the next available key:
public static TResult NextId<TSource, TResult>(this ObjectSet<TSource> table, Expression<Func<TSource, TResult>> selector)
where TSource : class
{
TResult lastId = table.Any() ? table.Max(selector) : default(TResult);
if (lastId is int)
{
lastId = (TResult)(object)(((int)(object)lastId) + 1);
}
return lastId;
}
Here's my take on the extension method: It will work fine if the ObjectContext that I am working with has an unfiltered entity set. In that case, the ObjectContext will contain all rows from the data table, and I will get an accurate result. But if the entity set is the result of a query filter, the method will return the last entity key in the filtered entity set, which will not necessarily be the last key in the data table. So I think the extension method won't really work.
At this point, the obvious solution seems to be to simply use a GUID as the entity key. That way, I only need to call Guid.NewGuid() method to set the ID property before I add a new entity to my ObjectContext.
Here is my question: Is there a simple way of getting the last primary key in the data store from EF4 (without having to create a second ObjectContext for that purpose)? Any other reason not to take the easy way out and simply use a GUID? Thanks for your help.
I ended up going with a GUID.
The size/performance issues aren't
critical (or even noticeable) with SQL Compact, since
it is a local, single-user system.
It's not like the app will be
managing an airline reservation
system.
And at least at this point, there
seems to be no way around the "no
server-generated keys" limitation of
the SQL Compact/EF4 stack. If someone has a clever hack, I'm still open to it.
That doesn't mean I would take the same approach in SQL Server or SQL Express. I still have a definite preference for integer keys, and SQL Compact's bigger siblings allow them in conjunction with EF4.
Use a Guid. AutoIncrement is not supported on Compact Framework with Entity Framework.
Also, if you ever want to create a application which uses multiple data sources, int PK's are going to fall apart on you very, very quickly.
With Guid's, you can juse call Guid.NewGuid() to get a new key.
With int's, you have to hit the database to get a valid key.
If you store data in multiple databases, int PK's will cause conflicts.
What I've done for SQL CE before, and I assume we have a single application accessing the database, is to calculate the MAX value on startup and put it in a static variable. You can now hand out sequential values easily and you can make the code to generate them thread safe very easily.
One reason to avoid Guids would be size = memory and storage space consumption.
You could also query SQL Compact metadata like so:
SELECT AUTOINC_NEXT FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Categories' AND AUTOINC_NEXT IS NOT NULL