Why is my DbModelBuilder configuration ignored when mapping Entity from DbSet<T>.SqlQuery?

谁都会走 提交于 2019-12-12 12:07:50

问题


I have a DbModel configuration like so:

modelBuilder.Entity<WishlistLine>()
            .HasKey(w => w.PersistenceKey)
            .Property(w => w.PersistenceKey)
            .HasColumnName("WishlistLineId");

I have a query run via the following two methods:

public IEnumerable<WishlistLine> FetchWishlistLinesUsingLogonName(string logonName)
{
        return GetFromRawSql(@"
    SELECT wl.* FROM WishlistLines wl
    INNER JOIN Accounts a ON wl.AccountId = a.AccountId 
    LEFT JOIN Users u ON u.AccountId = a.AccountId
    WHERE u.LogonName = @p0", logonName);
}

protected IEnumerable<TEntity> GetFromRawSql(string sqlQuery, params object[] parameters)
{
    return _dbSet.SqlQuery(sqlQuery, parameters).ToList();
}

I can "save" WishlistLines into the database through EF without any problems. When I run this query though I get this error:

The data reader is incompatible with the specified 'DataAccessLayer.DatabaseContext.WishlistLine'. A member of the type, 'PersistenceKey', does not have a corresponding column in the data reader with the same name.

I understood that using DbSet<T>.SqlQuery() would map the returned data to the entities but it seems to be ignoring the DbModel configurations. Judging (guessing) from the error message the wrong data reader is being used.

so:

A) am I doing anything wrong?

B) is there a way to make use of EF's DbModel-aware entity mapper?


回答1:


Indeed the column name mapping is ignored when you execute a raw SQL query. Here are two references: This pretty dissatisfying thread only for fun, but the following one with a serious answer from the EF team:

Quote from http://entityframework.codeplex.com/workitem/233:

The SqlQuery method is designed not to take any mapping into account, including mapping that is applied using attributes. It simply matches the column names from the results with property names in the object. If the column names don't match you will need to use a column alias (AS keyword in SQL Server) to rename the column in the results.

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, the only workaround seems to be an explicit AS alias instead of a * in your SQL query that specifies your property name as a column alias:

return GetFromRawSql(@"
    SELECT wl.WishlistLineId AS PersistenceKey,
           wl.SomeOtherColumn AS SomeOtherProperty,
           ...
    ..."
    // ...



回答2:


I found another solution that is quite clean. In my model, I have public properties with the nice names I want to use, and private properties with the exact same name as in the database, and return the private value in the getter of the public ones, like this:

public class KeywordsStatistic
{
    public string Keyword { get { return lib_motcle; } }
    public int NumActions { get { return nbrActions; } }

    private string lib_motcle { get; set; }
    private int nbrActions { get; set; }
}

Of course, this would need to be modified if the values need to be updated, but the principles are the same...

HTH



来源:https://stackoverflow.com/questions/12282757/why-is-my-dbmodelbuilder-configuration-ignored-when-mapping-entity-from-dbsett

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!