4

我有这样的DbModel配置:

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

我通过以下两种方法运行查询:

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();
}

我可以通过EF“保存”WishlistLines到数据库中,没有任何问题。当我运行此查询时,虽然我收到此错误:

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.

我知道 usingDbSet<T>.SqlQuery()会将返回的数据映射到实体,但它似乎忽略了DbModel配置。从错误消息判断(猜测)使用了错误的数据读取器。

所以:

A)我做错了什么吗?

B) 有没有办法利用 EF 的DbModel感知实体映射器?

4

2 回答 2

2

实际上,当您执行原始 SQL 查询时,列名映射会被忽略。这里有两个参考:这个非常不令人满意的线程只是为了好玩,但下面的一个来自 EF 团队的认真回答:

引用http://entityframework.codeplex.com/workitem/233

SqlQuery 方法旨在不考虑任何映射,包括使用属性应用的映射。它只是将结果中的列名与对象中的属性名相匹配。如果列名不匹配,您将需要使用列别名(SQL Server 中的 AS 关键字)来重命名结果中的列。

我们同意让 SqlQuery 尊重 Column 属性的选项会很有用,因此我们将保持此问题开放并将其放在我们的积压工作中以供将来考虑。

因此,唯一的解决方法似乎是显式AS别名,而不是*在 SQL 查询中将属性名称指定为列别名:

return GetFromRawSql(@"
    SELECT wl.WishlistLineId AS PersistenceKey,
           wl.SomeOtherColumn AS SomeOtherProperty,
           ...
    ..."
    // ...
于 2012-09-11T21:39:07.020 回答
0

我找到了另一个非常干净的解决方案。在我的模型中,我有具有我想要使用的好名称的公共属性,以及与数据库中的名称完全相同的私有属性,并在公共属性的 getter 中返回私有值,如下所示:

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; }
}

当然,如果需要更新值,则需要对其进行修改,但是原理是相同的...

高温高压

于 2015-10-21T14:25:47.070 回答