3

我在将通过存储过程查询的搜索结果映射到我的 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();

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

第二个是一个更大的问题。根据存储过程中的某些搜索值排名,在初始查询中以正确的顺序提取结果。然后,该订单在第二个查询中丢失,让我得到一个随机排序的结果集,并且无法(我可以看到)将其重新排序。

有任何想法吗?

4

1 回答 1

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>

感觉肮脏和骇人听闻,但现在必须这样做。当我找到一个不需要使用 .edmx 文件的更好的解决方案时,也许我会回到它。

于 2013-07-26T13:52:20.890 回答