为什么在从DbSet <t> .SqlQuery映射实体时忽略了我的DbModelBuilder配置?</t>

时间:2012-09-05 13:36:45

标签: c# entity-framework-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.

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

这样:

A)我做错了吗?

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

2 个答案:

答案 0 :(得分:2)

实际上,执行原始SQL查询时会忽略列名映射。以下是两个参考文献:This非常不满意的帖子只是为了好玩,但下面的一个得到了EF团队的认真答复:

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

  

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

     

我们同意拥有制作SqlQuery的选项会很有用   荣誉列属性,所以我们保持这个问题的开放和放置   它在我们的积压日期以供将来考虑。

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

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

答案 1 :(得分:0)

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

var memStream = new MemoryStream(yourPdfByteArray);
memStream.Position = 0;
var contentType = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Application.Pdf);
var reportAttachment = new Attachment(memStream, contentType);
reportAttachment.ContentDisposition.FileName = "yourFileName.pdf";
mailMessage.Attachments.Add(reportAttachment);

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

HTH