将存储过程结果映射到Entity Framework 5中的实体

时间:2013-07-25 19:55:44

标签: entity-framework asp.net-mvc-4 entity-framework-5

我将通过存储过程查询的搜索结果映射到我的EF实体时遇到了一些麻烦。我正在使用数据库第一种方法。

我可以轻松地使用DbContext.Database.SqlQuery<T>来检索简单实体,只要我的存储过程返回适当的列名,这就可以正常工作。然而,我的问题是我需要加载相关实体以及搜索结果。

这就是我正在使用的:

// Product.cs
public class Product
{
    public int ProductId { get; set; }
    public int CategoryId { get; set; }
    public int BrandId { get; set; }

    public virtual Category Category { get; set; }
    public virtual Brand Brand { get; set; }
}

// Category.cs
public class Category {
    public int CategoryId { get; set; }
    ...
    more properties
}

// Brand.cs
public class Brand {
    public int BrandId { get; set; }
    ...
    more properties
}

DbSet<Product>中提取数据时,一切都很有效,导航属性会按预期延迟加载。

是否有办法从存储过程中提取所有需要的数据,以便我的相关实体将被正确填充(即,我是否需要以某种特定方式命名我的列)?

我还尝试了第二种方法,我只需从存储过程中提取List<int> ProductId,然后使用Linq查询再次访问数据库以提取实体

List<int> results = unitOfWork.SqlQuery<int>(
    @"EXECUTE dbo.SomeStoredProcedure @Keyword",
    new SqlParameter("Keyword", keyword)
).ToList();

List<Product> products = unitOfWork.ProductRepository.Get(
    filter: q => results.Contains(q.ProductId)
).ToList();

这种方法出现了两个问题:两次访问数据库,某些地方的订单丢失了。我可以忍受的第一个问题,这是一个低流量的应用程序,我不担心额外的数据库之旅。

第二个问题是一个更大的问题。基于存储过程中的一些搜索值排名,结果在初始查询中以正确的顺序被拉出。然后该命令在第二个查询中丢失,留下一个随机排序的结果集,并且没有办法(我可以看到)将其重新订购。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我无法使.edmx映射工作,所以我最终坚持使用我的第二种方法并使用一种非常强硬的方式来使我的结果以他们应该的方式排序。

我使用原始问题中提到的两个查询来拉取我的实体(第一个列表的顺序正确):

List<int> results = unitOfWork.SqlQuery<int>(
    @"EXECUTE dbo.SomeStoredProcedure @Keyword",
    new SqlParameter("Keyword", keyword)
).ToList();

List<Product> products = unitOfWork.ProductRepository.Get(
    filter: q => results.Contains(q.ProductId)
).ToList();

我使用viewmodel将两个列表传递到我的视图:

public class SearchViewModel : BaseViewModel
{
    public SearchViewModel()
    {
        this.Results = new List<int>();
        this.Products = new List<Product>();
    }

    public string Keyword { get; set; }
    public List<int> Results { get; set; }
    public List<Product> Products { get; set; }
}

然后在视图级别而不是循环List<Product>,我遍历结果列表。

<ul class="products medium">
    @foreach(int productId in Model.Results){
        var product = Model.Products.FirstOrDefault(p => p.ProductId == productId);
        <li>
            ...
            display content
        </li>
    }
</ul>

感觉肮脏和hackish但现在必须做。当我找到一个不需要使用.edmx文件的更好的解决方案时,也许我会回过头来。