I'm using Entity Framework 5 (with Code First approach) to populate a class of mine from a legacy stored procedure with parameters, and this is working fine (details follow). My problem is that I want to map the columns' names to property with different names (I don't like the names coming from the Erp). I tried to use a Configuration class (like what I do when I map to views or tables) to specify the column name for properties with a different name, and here are my results:
- if I don't use the configuration class (I don't add it in the OnModelCreating method of the DbContext) then EF works but loads only the properties that match exactly with the name of the columns (and this is what I expected in this case); others property are null;
- if I use the configuration class (adding it to the modelBuilder in the OnModelCreating method of the DbContext) then EF raises an exception stating that "The data reader is incompatible with the specified '...Item'. A member of the type, 'Description', does not have a corresponding column in the data reader with the same name", and this sounds very strange to me, because in the configuration I specify that the property Description map to the column ItemDescription.
Why the configuration is affecting my result but its specification are not used to map the columns? Is there another way to specify this mapping using SqlQuery?
Here are the details:
My POCO class:
public class Item
{
public String Id { get; set; }
public String Description { get; set; }
}
The configuration class:
public class ItemConfiguration : EntityTypeConfiguration<Item>
{
public ItemConfiguration()
{
HasKey(x => new { x.Id });
Property(x => x.Id).HasColumnName("Code");
Property(x => x.Description).HasColumnName("ItemDescription");
}
}
The stored procedure return the data with the columns "Code" and "ItemDescription"; I call it in this way:
var par = new SqlParameter();
par.ParameterName = "@my_par";
par.Direction = ParameterDirection.Input;
par.SqlDbType = SqlDbType.VarChar;
par.Size = 20;
par.Value = ...;
var data = _context.Database.SqlQuery<Item>("exec spItem @my_par", par);
and with this I add the configuration to the context:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ItemConfiguration());
}
Thank you!
After some years using bubi's approach, and implementing some code, I decided to post our improvements in here. Please, be advised that there are references to other namespaces which I WON'T post. Just adapt it to your needs.
Anyway, I hope it helps somebody.
I found here:
http://entityframework.codeplex.com/workitem/233?PendingVoteId=233
that "The SqlQuery method is designed not to take any mapping into account ...".
They say also "We agree that it would be useful to have the option to make SqlQuery honor Column attributes so we're keeping this issue open and putting it on our backlog for future consideration.", so, if you have my same problem, please vote :-)
Meanwhile, you can use this method. Few tests (because it worked for my classes) but not to difficult to fix if needed... It need a context (to retrieve mapped custom types) and it need a different connection to run a datareader on it at the same time.
Usage:
List students = Mapper.Map(context, (new SchoolContext()).Database.Connection, "Select * from Students");
I,ve just write bellow extention method to convert sql query to a property named sql and then query data.
hope be useful