Linq 到实体并包含?

发布于 2024-10-29 05:17:47 字数 21997 浏览 1 评论 0原文

嗨,

我有一个像这样的 linq to sql 问题:

tmpAdList1 = (from p in context.Ads
                            join h in context.AdCategories on p.CategoryId equals h.Id
                            join l in context.Location on p.UserLocationId equals l.Id
                            where
                            (adList.S == null || adList.S.Length < 1 || p.Title.Contains(adList.S) || p.Description.Contains(adList.S)) &&
                            (categorylevelOrder.Length < 1 || h.LevelOrder.StartsWith(categorylevelOrder)) &&

                            ((locationIdList != null && lList.Contains(l.Id)) ||
                            (locationLevelOrder.Length < 1 || l.LevelOrder.StartsWith(locationLevelOrder))) &&

                            ((adTypeO1 == AdType.Unknown && adTypeO2 == AdType.Unknown && adTypeO3 == AdType.Unknown && adTypeO4 == AdType.Unknown && adTypeO5 == AdType.Unknown) ||
                            (p.TypeOfAd == (int)adTypeO1 || p.TypeOfAd == (int)adTypeO2 || p.TypeOfAd == (int)adTypeO3 || p.TypeOfAd == (int)adTypeO4 || p.TypeOfAd == (int)adTypeO5)) && //Check for default filters
                            ((AdListShowType)adList.ALS.ST == AdListShowType.Both || adList.ALS.ST == p.OwnerType) &&
                            (p.PublishedDate.HasValue && p.PublishedDate.Value.CompareTo(fetchAdsTo) >= 1) &&
                            ((adOwnerType1.HasValue && adOwnerType2.HasValue) || p.OwnerType == (int)adOwnerType1.Value) &&
                            p.InactivatedDate == null
                            orderby p.CreatedDate descending
                            select p).ToList();

请参阅 Edit1 了解整个方法

运行此问题后,将进行更多过滤(在上下文中),但要尽可能快地完成第一个问题,我的目标是从 SQL 服务器获取尽可能少的记录。

问题是我需要将 int[] 的 locationIdList 与实体进行比较。抛出的异常是:

无法比较“System.Int32[]”类型的元素。仅支持原始类型(例如 Int32、String 和 Guid)和实体类型。

我在 google 上搜索了该问题,这是一个已知问题,但是我发现了这样的示例:

var list = new List<int> { 1, 2, 3, 5 };
var result = from s in DB.Something
             where list.Contains(s.Id)
             select s;

但这会引发相同的异常?我还读到存储过程可以解决问题,但我还没有找到它是如何工作的?

有什么建议吗?

BestRegards

编辑 1: 整个方法:

public List<Ad> GetAds(AdList adList, DateTime fetchAdsTo, out int totalAds)
{
    AdType adTypeO1 = AdType.Unknown;
    AdType adTypeO2 = AdType.Unknown;
    AdType adTypeO3 = AdType.Unknown;
    AdType adTypeO4 = AdType.Unknown;
    AdType adTypeO5 = AdType.Unknown;

    int? adOwnerType1 = null;
    int? adOwnerType2 = null;

    FilterModel filterModel = new FilterModel();

    List<AdCategoryFilter> adCategoryFilterList;
    AdsFilterValues adsFilterValues;
    List<AdsFilterValueWrapper> seartchFilterValueList;
    AdsFilterValueWrapper seartchFilterValue = null;
    List<Ad> tmpAdList1;
    List<Ad> tmpAdList2 = new List<Ad>();

    int locationId = -1;
    int[] locationIdList = null;
    string locationLevelOrder = string.Empty;

    int categoryId = -1;
    string categorylevelOrder = string.Empty;

    AdCategoryFilter adCategoryFilter;

    AdListCompare adListCompare;

    Boolean firstDropDownMatch = false;
    Boolean secondDropDownMatch = false;

    totalAds = 0;

    int machedFilterCount;

    categoryId = AdHandler.Instance.ExtractCategoryId(adList.CS);

    //If there is multiple choises
    //This is the last level, that means that we can check against the ID dircly
    if (adList.LS.L3.Count > 0)
        locationIdList = adList.LS.L3.ToArray();
    else
        locationId = AdHandler.Instance.ExtractLocationId(adList.LS);


    switch ((AdOwnerType)adList.ALS.ST)
    {
        case AdOwnerType.Both:
            adOwnerType1 = (int)AdOwnerType.Private;
            adOwnerType2 = (int)AdOwnerType.Company;
            break;
        case AdOwnerType.Company:
            adOwnerType1 = (int)AdOwnerType.Company;
            break;
        case AdOwnerType.Private:
            adOwnerType1 = (int)AdOwnerType.Private;
            break;
    }

    #region GetFilters
    adCategoryFilterList = filterModel.GetCategoryFilterByCategory(categoryId);
    seartchFilterValueList = FilterHandler.Instance.ConvertAdFilterToModel(adList.F, adCategoryFilterList, FilterType.Display);
    #endregion

    #region Set Default filters (Buy, Let, Sell, Swap, WishRent)
    foreach (AdsFilterValueWrapper filterWrapper in seartchFilterValueList)
    {
        if ((adCategoryFilter = adCategoryFilterList.Where(c => c.Id == filterWrapper.FilterId).FirstOrDefault()) != null)
        {
            switch ((PublicAdFilterKey)adCategoryFilter.PublicAdFilterKey)
            {
                case PublicAdFilterKey.Buy:
                    {
                        if (filterWrapper.AdsFilterValues1.ValueNumber > 0)
                            adTypeO1 = AdType.Buy;
                        break;
                    }
                case PublicAdFilterKey.Let:
                    {
                        if (filterWrapper.AdsFilterValues1.ValueNumber > 0)
                            adTypeO2 = AdType.Let;
                        break;
                    }
                case PublicAdFilterKey.Sell:
                    {
                        if (filterWrapper.AdsFilterValues1.ValueNumber > 0)
                            adTypeO3 = AdType.Sell;
                        break;
                    }
                case PublicAdFilterKey.Swap:
                    {
                        if (filterWrapper.AdsFilterValues1.ValueNumber > 0)
                            adTypeO4 = AdType.Swap;
                        break;
                    }
                case PublicAdFilterKey.WishRent:
                    {
                        if (filterWrapper.AdsFilterValues1.ValueNumber > 0)
                            adTypeO5 = AdType.WishRent;
                        break;
                    }
            }
        }
    }

    #region Remove default filters fom filterList
    adCategoryFilterList = adCategoryFilterList.Where(c => ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.Buy &&
                                    ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.Let &&
                                    ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.Sell &&
                                    ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.Swap &&
                                    ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.WishRent).ToList();
    #endregion
    #endregion

    var lList = adList.LS.L3.ToList<int>(); //new List<int> { 1, 2, 3, 5 };


    using (BissEntities context = new BissEntities())
    {
        if (categoryId > 0)
            categorylevelOrder = context.AdCategories.Where(c => c.Id.Equals(categoryId)).FirstOrDefault().LevelOrder.Trim();
        if (locationId > 0)
            locationLevelOrder = context.Location.Where(c => c.Id.Equals(locationId)).FirstOrDefault().LevelOrder.Trim();

        tmpAdList1 = (from p in context.Ads
                        join h in context.AdCategories on p.CategoryId equals h.Id
                        join l in context.Location on p.UserLocationId equals l.Id
                        where
                        (adList.S == null || adList.S.Length < 1 || p.Title.Contains(adList.S) || p.Description.Contains(adList.S)) &&
                        (categorylevelOrder.Length < 1 || h.LevelOrder.StartsWith(categorylevelOrder)) &&

                        ((locationIdList != null && lList.Contains(l.Id)) ||
                        (locationLevelOrder.Length < 1 || l.LevelOrder.StartsWith(locationLevelOrder))) &&

                        ((adTypeO1 == AdType.Unknown && adTypeO2 == AdType.Unknown && adTypeO3 == AdType.Unknown && adTypeO4 == AdType.Unknown && adTypeO5 == AdType.Unknown) ||
                        (p.TypeOfAd == (int)adTypeO1 || p.TypeOfAd == (int)adTypeO2 || p.TypeOfAd == (int)adTypeO3 || p.TypeOfAd == (int)adTypeO4 || p.TypeOfAd == (int)adTypeO5)) && //Check for default filters
                        ((AdListShowType)adList.ALS.ST == AdListShowType.Both || adList.ALS.ST == p.OwnerType) &&
                        (p.PublishedDate.HasValue && p.PublishedDate.Value.CompareTo(fetchAdsTo) >= 1) &&
                        ((adOwnerType1.HasValue && adOwnerType2.HasValue) || p.OwnerType == (int)adOwnerType1.Value) &&
                        p.InactivatedDate == null
                        orderby p.CreatedDate descending
                        select p).ToList();

        #region Filter collection
        foreach (Ad ad in tmpAdList1)
        {
            machedFilterCount = 0;
            adListCompare = AdListCompare.NotCompered;

            if (adCategoryFilterList.Count > 0)
            {                     
                //Loop the filters that belongs to the choosen category
                foreach (AdCategoryFilter existingFilter in adCategoryFilterList)
                {
                    //Se if the ad has the proper filter If not return it
                    if ((adsFilterValues = ad.AdsFilterValues.Where(c => c.CategoryFilterId == existingFilter.Id).FirstOrDefault()) != null || existingFilter.PublicAdFilterKey > 0)
                    {

                        //If the filter is not a regular value filter but a filter pointed to a property on the ad
                        //Then extract the correct value and use it
                        if (existingFilter.PublicAdFilterKey > 0)
                        {
                            adsFilterValues = new AdsFilterValues();
                            adsFilterValues.CategoryFilterId = existingFilter.Id;

                            switch ((PublicAdFilterKey)existingFilter.PublicAdFilterKey)
                            {
                                case PublicAdFilterKey.Price:
                                    {
                                        adsFilterValues.ValueNumber = ad.Price;
                                        break;
                                    }
                            }

                        }

                        if ((seartchFilterValue = seartchFilterValueList.Where(c => c.AdsFilterValues1.CategoryFilterId == adsFilterValues.CategoryFilterId).FirstOrDefault()) != null)
                        {
                            firstDropDownMatch = false;
                            secondDropDownMatch = false;
                            adListCompare = AdListCompare.Compared;

                            switch ((FilterControlType)existingFilter.DisplayFilterControlType)
                            {
                                case FilterControlType.TwoDropDown:

                                    //Check so the first dropdown value compare
                                    //If the index is the first then any value will do
                                    if (seartchFilterValue.FilterIndexPosition1 == FilterIndexPosition.First)
                                        firstDropDownMatch = true;
                                    else
                                    {
                                        if (adsFilterValues.ValueNumber.Value >= seartchFilterValue.AdsFilterValues1.ValueNumber.Value)
                                            firstDropDownMatch = true;
                                    }

                                    if (firstDropDownMatch)
                                    {
                                        //Check so the second dropdown value compare
                                        //If the index is the last then any value will do
                                        if (seartchFilterValue.FilterIndexPosition2 == FilterIndexPosition.Last)
                                            secondDropDownMatch = true;
                                        else
                                        {
                                            if (adsFilterValues.ValueNumber.Value <= seartchFilterValue.AdsFilterValues2.ValueNumber.Value)
                                                secondDropDownMatch = true;
                                        }

                                        if (secondDropDownMatch)
                                            adListCompare = AdListCompare.Approved;
                                    }

                                    break;
                                case FilterControlType.DropDown:

                                    //Check so the first dropdown value compare
                                    //If the index is the first then any value will do
                                    if (seartchFilterValue.FilterIndexPosition1 == FilterIndexPosition.First)
                                    {
                                        if (adsFilterValues.ValueNumber.Value <= seartchFilterValue.AdsFilterValues1.ValueNumber.Value)
                                            firstDropDownMatch = true;
                                    }
                                    if (seartchFilterValue.FilterIndexPosition1 == FilterIndexPosition.Last)
                                    {
                                        if (adsFilterValues.ValueNumber.Value >= seartchFilterValue.AdsFilterValues1.ValueNumber.Value)
                                            firstDropDownMatch = true;
                                    }
                                    else
                                    {
                                        if (adsFilterValues.ValueNumber.Value == seartchFilterValue.AdsFilterValues1.ValueNumber.Value)
                                            firstDropDownMatch = true;
                                    }

                                    if (firstDropDownMatch)
                                        adListCompare = AdListCompare.Approved;

                                    break;
                                case FilterControlType.TextBox:
                                    if (adsFilterValues.ValueString.Equals(seartchFilterValue.AdsFilterValues1.ValueString))
                                        adListCompare = AdListCompare.Approved;
                                    break;
                                case FilterControlType.CheckBox:
                                    if (adsFilterValues.ValueNumber != null && adsFilterValues.ValueNumber.Value == seartchFilterValue.AdsFilterValues1.ValueNumber.Value)
                                        adListCompare = AdListCompare.Approved;
                                    break;
                                default:
                                    adListCompare = AdListCompare.NotCompered;
                                    break;
                            }

                            //If no value is set, then break;
                            if (adListCompare != AdListCompare.Approved)
                                break;

                            machedFilterCount++;
                        }
                    }
                    else
                    {
                        //If the ad is missing the filter then return it anyway, it might as well be correct
                        adListCompare = AdListCompare.Approved;
                        machedFilterCount = adCategoryFilterList.Count();
                    }
                }
            }
            else
            {
                adListCompare = AdListCompare.Approved;
                machedFilterCount = adCategoryFilterList.Count();
            }


            if (adListCompare == AdListCompare.Approved && machedFilterCount == adCategoryFilterList.Count())
                tmpAdList2.Add(ad);
        }
        #endregion

        if (adList.ALS.OB == (int)AdListOrderBy.Price)
            tmpAdList2 = tmpAdList2.OrderBy(c => c.Price).ToList();


        totalAds = tmpAdList2.Count();

        return tmpAdList2.Skip((adList.ALS.P - 1) * adList.ALS.CP).Take(adList.ALS.CP).ToList();
    }
}

编辑 2:更新

主 GetAd 方法:

public List<Ad> GetAds(AdList adList, DateTime fetchAdsTo, out int totalAds)
        {
            LocationModel locationModel = new LocationModel();
            FilterModel filterModel = new FilterModel();

            List<AdCategoryFilter> adCategoryFilterList;
            List<AdsFilterValueWrapper> seartchFilterValueList;

            int categoryId = -1;
            List<Ad> outputList;

            totalAds = 0;

            #region Fetch the first ads by location
            outputList = GetAdsByLocations(locationModel.GetLocationOrderList(adList.GetLocationIds()), fetchAdsTo, false);
            if(outputList.Count < 1)
                return outputList;
            #endregion

            #region GetFilters
            categoryId = AdHandler.Instance.ExtractCategoryId(adList.CS);
            adCategoryFilterList = filterModel.GetCategoryFilterByCategory(categoryId);
            seartchFilterValueList = FilterHandler.Instance.ConvertAdFilterToModel(adList.F, adCategoryFilterList, FilterType.Display);
            #endregion

            #region Filter Default filters (Buy, Let, Sell, Swap, WishRent)
            FilterDefaultCustomFilters(outputList, adCategoryFilterList, seartchFilterValueList);
            if (outputList.Count == 0)
                return outputList;
            else
            {
                #region Remove default filters fom filterList
                adCategoryFilterList = adCategoryFilterList.Where(c => ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.Buy &&
                                                ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.Let &&
                                                ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.Sell &&
                                                ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.Swap &&
                                                ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.WishRent).ToList();
                #endregion
            }
            #endregion

            #region Filter Custom filters
            this.FilterCustomFilters(outputList, adCategoryFilterList, seartchFilterValueList);
            #endregion

            #region Order
            switch ((AdListOrderBy)adList.ALS.OB)
            {
                case AdListOrderBy.Price:
                    outputList = outputList.OrderBy(c => c.Price).ToList(); break;
                case AdListOrderBy.Latest:
                    outputList = outputList.OrderByDescending(c => c.PublishedDate).ToList(); break;
            }
            #endregion

            #region Total Ad Count
            totalAds = outputList.Count();
            #endregion

            #region Paging
            outputList = outputList.Skip((adList.ALS.P - 1) * adList.ALS.CP).Take(adList.ALS.CP).ToList();
            #endregion

            return outputList;
        }

GetAdByLocation strong>

public List<Ad> GetAdsByLocations(string[] locationLevelOrderList, DateTime? fetchAdsTo, Boolean inactive) //, List<Ad> adList = null)
{
    List<Ad> output;

    using (BissEntities context = new BissEntities())
    {
        if (fetchAdsTo.HasValue)
        {
            if (locationLevelOrderList.Count() == 0)
            {
                output = (from a in context.Ads
                            join l in context.Location on a.UserLocationId equals l.Id
                            where a.InactivatedDate.HasValue == inactive &&
                            (a.PublishedDate.HasValue && a.PublishedDate.Value.CompareTo(fetchAdsTo.Value) >= 1)
                            select a).ToList();
            }
            else
            {
                output = (from a in context.Ads
                            join l in context.Location on a.UserLocationId equals l.Id
                            where a.InactivatedDate.HasValue == inactive &&
                            (a.PublishedDate.HasValue && a.PublishedDate.Value.CompareTo(fetchAdsTo.Value) >= 1) &&
                            (locationLevelOrderList.Where(c => l.LevelOrder.StartsWith(c)).FirstOrDefault() != null) 
                            select a).ToList();
            }

        }
        else
        {
            if (locationLevelOrderList.Count() == 0)
            {
                output = (from a in context.Ads
                            join l in context.Location on a.UserLocationId equals l.Id
                            where a.InactivatedDate.HasValue == inactive
                            select a).ToList();
            }
            else
            {
                output = (from a in context.Ads
                            join l in context.Location on a.UserLocationId equals l.Id
                            where a.InactivatedDate.HasValue == inactive &&
                            (locationLevelOrderList.Count() == 0 || locationLevelOrderList.Where(c => l.LevelOrder.StartsWith(c)).FirstOrDefault() != null)
                            select a).ToList();
            }
        }
    }

    return output;
}

注意: 主 GetAd 中名称以 Filter 开头的方法仅适用于集合(无数据库操作)

Hi,

I have a linq to sql question like this :

tmpAdList1 = (from p in context.Ads
                            join h in context.AdCategories on p.CategoryId equals h.Id
                            join l in context.Location on p.UserLocationId equals l.Id
                            where
                            (adList.S == null || adList.S.Length < 1 || p.Title.Contains(adList.S) || p.Description.Contains(adList.S)) &&
                            (categorylevelOrder.Length < 1 || h.LevelOrder.StartsWith(categorylevelOrder)) &&

                            ((locationIdList != null && lList.Contains(l.Id)) ||
                            (locationLevelOrder.Length < 1 || l.LevelOrder.StartsWith(locationLevelOrder))) &&

                            ((adTypeO1 == AdType.Unknown && adTypeO2 == AdType.Unknown && adTypeO3 == AdType.Unknown && adTypeO4 == AdType.Unknown && adTypeO5 == AdType.Unknown) ||
                            (p.TypeOfAd == (int)adTypeO1 || p.TypeOfAd == (int)adTypeO2 || p.TypeOfAd == (int)adTypeO3 || p.TypeOfAd == (int)adTypeO4 || p.TypeOfAd == (int)adTypeO5)) && //Check for default filters
                            ((AdListShowType)adList.ALS.ST == AdListShowType.Both || adList.ALS.ST == p.OwnerType) &&
                            (p.PublishedDate.HasValue && p.PublishedDate.Value.CompareTo(fetchAdsTo) >= 1) &&
                            ((adOwnerType1.HasValue && adOwnerType2.HasValue) || p.OwnerType == (int)adOwnerType1.Value) &&
                            p.InactivatedDate == null
                            orderby p.CreatedDate descending
                            select p).ToList();

See Edit1 for the whole method

After this question is runned some more filtering will be done(within the context) but to make this as fast as possible I aim to fetch as little records as possible from the SQL server in the first question.

The problem is that I need to compare locationIdList that is a int[] to the entity. The exception thrown is :

Cannot compare elements of type 'System.Int32[]'. Only primitive types (such as Int32, String, and Guid) and entity types are supported.

I have google the problem and this is a known problem, I have however found examples like this :

var list = new List<int> { 1, 2, 3, 5 };
var result = from s in DB.Something
             where list.Contains(s.Id)
             select s;

But this throws the same exception? I have also read that a storedprocedure could solve the problem but I havent found how this work?

Any suggestions?

BestRegards

Edit1 : The entire method :

public List<Ad> GetAds(AdList adList, DateTime fetchAdsTo, out int totalAds)
{
    AdType adTypeO1 = AdType.Unknown;
    AdType adTypeO2 = AdType.Unknown;
    AdType adTypeO3 = AdType.Unknown;
    AdType adTypeO4 = AdType.Unknown;
    AdType adTypeO5 = AdType.Unknown;

    int? adOwnerType1 = null;
    int? adOwnerType2 = null;

    FilterModel filterModel = new FilterModel();

    List<AdCategoryFilter> adCategoryFilterList;
    AdsFilterValues adsFilterValues;
    List<AdsFilterValueWrapper> seartchFilterValueList;
    AdsFilterValueWrapper seartchFilterValue = null;
    List<Ad> tmpAdList1;
    List<Ad> tmpAdList2 = new List<Ad>();

    int locationId = -1;
    int[] locationIdList = null;
    string locationLevelOrder = string.Empty;

    int categoryId = -1;
    string categorylevelOrder = string.Empty;

    AdCategoryFilter adCategoryFilter;

    AdListCompare adListCompare;

    Boolean firstDropDownMatch = false;
    Boolean secondDropDownMatch = false;

    totalAds = 0;

    int machedFilterCount;

    categoryId = AdHandler.Instance.ExtractCategoryId(adList.CS);

    //If there is multiple choises
    //This is the last level, that means that we can check against the ID dircly
    if (adList.LS.L3.Count > 0)
        locationIdList = adList.LS.L3.ToArray();
    else
        locationId = AdHandler.Instance.ExtractLocationId(adList.LS);


    switch ((AdOwnerType)adList.ALS.ST)
    {
        case AdOwnerType.Both:
            adOwnerType1 = (int)AdOwnerType.Private;
            adOwnerType2 = (int)AdOwnerType.Company;
            break;
        case AdOwnerType.Company:
            adOwnerType1 = (int)AdOwnerType.Company;
            break;
        case AdOwnerType.Private:
            adOwnerType1 = (int)AdOwnerType.Private;
            break;
    }

    #region GetFilters
    adCategoryFilterList = filterModel.GetCategoryFilterByCategory(categoryId);
    seartchFilterValueList = FilterHandler.Instance.ConvertAdFilterToModel(adList.F, adCategoryFilterList, FilterType.Display);
    #endregion

    #region Set Default filters (Buy, Let, Sell, Swap, WishRent)
    foreach (AdsFilterValueWrapper filterWrapper in seartchFilterValueList)
    {
        if ((adCategoryFilter = adCategoryFilterList.Where(c => c.Id == filterWrapper.FilterId).FirstOrDefault()) != null)
        {
            switch ((PublicAdFilterKey)adCategoryFilter.PublicAdFilterKey)
            {
                case PublicAdFilterKey.Buy:
                    {
                        if (filterWrapper.AdsFilterValues1.ValueNumber > 0)
                            adTypeO1 = AdType.Buy;
                        break;
                    }
                case PublicAdFilterKey.Let:
                    {
                        if (filterWrapper.AdsFilterValues1.ValueNumber > 0)
                            adTypeO2 = AdType.Let;
                        break;
                    }
                case PublicAdFilterKey.Sell:
                    {
                        if (filterWrapper.AdsFilterValues1.ValueNumber > 0)
                            adTypeO3 = AdType.Sell;
                        break;
                    }
                case PublicAdFilterKey.Swap:
                    {
                        if (filterWrapper.AdsFilterValues1.ValueNumber > 0)
                            adTypeO4 = AdType.Swap;
                        break;
                    }
                case PublicAdFilterKey.WishRent:
                    {
                        if (filterWrapper.AdsFilterValues1.ValueNumber > 0)
                            adTypeO5 = AdType.WishRent;
                        break;
                    }
            }
        }
    }

    #region Remove default filters fom filterList
    adCategoryFilterList = adCategoryFilterList.Where(c => ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.Buy &&
                                    ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.Let &&
                                    ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.Sell &&
                                    ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.Swap &&
                                    ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.WishRent).ToList();
    #endregion
    #endregion

    var lList = adList.LS.L3.ToList<int>(); //new List<int> { 1, 2, 3, 5 };


    using (BissEntities context = new BissEntities())
    {
        if (categoryId > 0)
            categorylevelOrder = context.AdCategories.Where(c => c.Id.Equals(categoryId)).FirstOrDefault().LevelOrder.Trim();
        if (locationId > 0)
            locationLevelOrder = context.Location.Where(c => c.Id.Equals(locationId)).FirstOrDefault().LevelOrder.Trim();

        tmpAdList1 = (from p in context.Ads
                        join h in context.AdCategories on p.CategoryId equals h.Id
                        join l in context.Location on p.UserLocationId equals l.Id
                        where
                        (adList.S == null || adList.S.Length < 1 || p.Title.Contains(adList.S) || p.Description.Contains(adList.S)) &&
                        (categorylevelOrder.Length < 1 || h.LevelOrder.StartsWith(categorylevelOrder)) &&

                        ((locationIdList != null && lList.Contains(l.Id)) ||
                        (locationLevelOrder.Length < 1 || l.LevelOrder.StartsWith(locationLevelOrder))) &&

                        ((adTypeO1 == AdType.Unknown && adTypeO2 == AdType.Unknown && adTypeO3 == AdType.Unknown && adTypeO4 == AdType.Unknown && adTypeO5 == AdType.Unknown) ||
                        (p.TypeOfAd == (int)adTypeO1 || p.TypeOfAd == (int)adTypeO2 || p.TypeOfAd == (int)adTypeO3 || p.TypeOfAd == (int)adTypeO4 || p.TypeOfAd == (int)adTypeO5)) && //Check for default filters
                        ((AdListShowType)adList.ALS.ST == AdListShowType.Both || adList.ALS.ST == p.OwnerType) &&
                        (p.PublishedDate.HasValue && p.PublishedDate.Value.CompareTo(fetchAdsTo) >= 1) &&
                        ((adOwnerType1.HasValue && adOwnerType2.HasValue) || p.OwnerType == (int)adOwnerType1.Value) &&
                        p.InactivatedDate == null
                        orderby p.CreatedDate descending
                        select p).ToList();

        #region Filter collection
        foreach (Ad ad in tmpAdList1)
        {
            machedFilterCount = 0;
            adListCompare = AdListCompare.NotCompered;

            if (adCategoryFilterList.Count > 0)
            {                     
                //Loop the filters that belongs to the choosen category
                foreach (AdCategoryFilter existingFilter in adCategoryFilterList)
                {
                    //Se if the ad has the proper filter If not return it
                    if ((adsFilterValues = ad.AdsFilterValues.Where(c => c.CategoryFilterId == existingFilter.Id).FirstOrDefault()) != null || existingFilter.PublicAdFilterKey > 0)
                    {

                        //If the filter is not a regular value filter but a filter pointed to a property on the ad
                        //Then extract the correct value and use it
                        if (existingFilter.PublicAdFilterKey > 0)
                        {
                            adsFilterValues = new AdsFilterValues();
                            adsFilterValues.CategoryFilterId = existingFilter.Id;

                            switch ((PublicAdFilterKey)existingFilter.PublicAdFilterKey)
                            {
                                case PublicAdFilterKey.Price:
                                    {
                                        adsFilterValues.ValueNumber = ad.Price;
                                        break;
                                    }
                            }

                        }

                        if ((seartchFilterValue = seartchFilterValueList.Where(c => c.AdsFilterValues1.CategoryFilterId == adsFilterValues.CategoryFilterId).FirstOrDefault()) != null)
                        {
                            firstDropDownMatch = false;
                            secondDropDownMatch = false;
                            adListCompare = AdListCompare.Compared;

                            switch ((FilterControlType)existingFilter.DisplayFilterControlType)
                            {
                                case FilterControlType.TwoDropDown:

                                    //Check so the first dropdown value compare
                                    //If the index is the first then any value will do
                                    if (seartchFilterValue.FilterIndexPosition1 == FilterIndexPosition.First)
                                        firstDropDownMatch = true;
                                    else
                                    {
                                        if (adsFilterValues.ValueNumber.Value >= seartchFilterValue.AdsFilterValues1.ValueNumber.Value)
                                            firstDropDownMatch = true;
                                    }

                                    if (firstDropDownMatch)
                                    {
                                        //Check so the second dropdown value compare
                                        //If the index is the last then any value will do
                                        if (seartchFilterValue.FilterIndexPosition2 == FilterIndexPosition.Last)
                                            secondDropDownMatch = true;
                                        else
                                        {
                                            if (adsFilterValues.ValueNumber.Value <= seartchFilterValue.AdsFilterValues2.ValueNumber.Value)
                                                secondDropDownMatch = true;
                                        }

                                        if (secondDropDownMatch)
                                            adListCompare = AdListCompare.Approved;
                                    }

                                    break;
                                case FilterControlType.DropDown:

                                    //Check so the first dropdown value compare
                                    //If the index is the first then any value will do
                                    if (seartchFilterValue.FilterIndexPosition1 == FilterIndexPosition.First)
                                    {
                                        if (adsFilterValues.ValueNumber.Value <= seartchFilterValue.AdsFilterValues1.ValueNumber.Value)
                                            firstDropDownMatch = true;
                                    }
                                    if (seartchFilterValue.FilterIndexPosition1 == FilterIndexPosition.Last)
                                    {
                                        if (adsFilterValues.ValueNumber.Value >= seartchFilterValue.AdsFilterValues1.ValueNumber.Value)
                                            firstDropDownMatch = true;
                                    }
                                    else
                                    {
                                        if (adsFilterValues.ValueNumber.Value == seartchFilterValue.AdsFilterValues1.ValueNumber.Value)
                                            firstDropDownMatch = true;
                                    }

                                    if (firstDropDownMatch)
                                        adListCompare = AdListCompare.Approved;

                                    break;
                                case FilterControlType.TextBox:
                                    if (adsFilterValues.ValueString.Equals(seartchFilterValue.AdsFilterValues1.ValueString))
                                        adListCompare = AdListCompare.Approved;
                                    break;
                                case FilterControlType.CheckBox:
                                    if (adsFilterValues.ValueNumber != null && adsFilterValues.ValueNumber.Value == seartchFilterValue.AdsFilterValues1.ValueNumber.Value)
                                        adListCompare = AdListCompare.Approved;
                                    break;
                                default:
                                    adListCompare = AdListCompare.NotCompered;
                                    break;
                            }

                            //If no value is set, then break;
                            if (adListCompare != AdListCompare.Approved)
                                break;

                            machedFilterCount++;
                        }
                    }
                    else
                    {
                        //If the ad is missing the filter then return it anyway, it might as well be correct
                        adListCompare = AdListCompare.Approved;
                        machedFilterCount = adCategoryFilterList.Count();
                    }
                }
            }
            else
            {
                adListCompare = AdListCompare.Approved;
                machedFilterCount = adCategoryFilterList.Count();
            }


            if (adListCompare == AdListCompare.Approved && machedFilterCount == adCategoryFilterList.Count())
                tmpAdList2.Add(ad);
        }
        #endregion

        if (adList.ALS.OB == (int)AdListOrderBy.Price)
            tmpAdList2 = tmpAdList2.OrderBy(c => c.Price).ToList();


        totalAds = tmpAdList2.Count();

        return tmpAdList2.Skip((adList.ALS.P - 1) * adList.ALS.CP).Take(adList.ALS.CP).ToList();
    }
}

Edit 2: update

The main GetAd Method :

public List<Ad> GetAds(AdList adList, DateTime fetchAdsTo, out int totalAds)
        {
            LocationModel locationModel = new LocationModel();
            FilterModel filterModel = new FilterModel();

            List<AdCategoryFilter> adCategoryFilterList;
            List<AdsFilterValueWrapper> seartchFilterValueList;

            int categoryId = -1;
            List<Ad> outputList;

            totalAds = 0;

            #region Fetch the first ads by location
            outputList = GetAdsByLocations(locationModel.GetLocationOrderList(adList.GetLocationIds()), fetchAdsTo, false);
            if(outputList.Count < 1)
                return outputList;
            #endregion

            #region GetFilters
            categoryId = AdHandler.Instance.ExtractCategoryId(adList.CS);
            adCategoryFilterList = filterModel.GetCategoryFilterByCategory(categoryId);
            seartchFilterValueList = FilterHandler.Instance.ConvertAdFilterToModel(adList.F, adCategoryFilterList, FilterType.Display);
            #endregion

            #region Filter Default filters (Buy, Let, Sell, Swap, WishRent)
            FilterDefaultCustomFilters(outputList, adCategoryFilterList, seartchFilterValueList);
            if (outputList.Count == 0)
                return outputList;
            else
            {
                #region Remove default filters fom filterList
                adCategoryFilterList = adCategoryFilterList.Where(c => ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.Buy &&
                                                ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.Let &&
                                                ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.Sell &&
                                                ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.Swap &&
                                                ((PublicAdFilterKey)c.PublicAdFilterKey) != PublicAdFilterKey.WishRent).ToList();
                #endregion
            }
            #endregion

            #region Filter Custom filters
            this.FilterCustomFilters(outputList, adCategoryFilterList, seartchFilterValueList);
            #endregion

            #region Order
            switch ((AdListOrderBy)adList.ALS.OB)
            {
                case AdListOrderBy.Price:
                    outputList = outputList.OrderBy(c => c.Price).ToList(); break;
                case AdListOrderBy.Latest:
                    outputList = outputList.OrderByDescending(c => c.PublishedDate).ToList(); break;
            }
            #endregion

            #region Total Ad Count
            totalAds = outputList.Count();
            #endregion

            #region Paging
            outputList = outputList.Skip((adList.ALS.P - 1) * adList.ALS.CP).Take(adList.ALS.CP).ToList();
            #endregion

            return outputList;
        }

GetAdByLocation

public List<Ad> GetAdsByLocations(string[] locationLevelOrderList, DateTime? fetchAdsTo, Boolean inactive) //, List<Ad> adList = null)
{
    List<Ad> output;

    using (BissEntities context = new BissEntities())
    {
        if (fetchAdsTo.HasValue)
        {
            if (locationLevelOrderList.Count() == 0)
            {
                output = (from a in context.Ads
                            join l in context.Location on a.UserLocationId equals l.Id
                            where a.InactivatedDate.HasValue == inactive &&
                            (a.PublishedDate.HasValue && a.PublishedDate.Value.CompareTo(fetchAdsTo.Value) >= 1)
                            select a).ToList();
            }
            else
            {
                output = (from a in context.Ads
                            join l in context.Location on a.UserLocationId equals l.Id
                            where a.InactivatedDate.HasValue == inactive &&
                            (a.PublishedDate.HasValue && a.PublishedDate.Value.CompareTo(fetchAdsTo.Value) >= 1) &&
                            (locationLevelOrderList.Where(c => l.LevelOrder.StartsWith(c)).FirstOrDefault() != null) 
                            select a).ToList();
            }

        }
        else
        {
            if (locationLevelOrderList.Count() == 0)
            {
                output = (from a in context.Ads
                            join l in context.Location on a.UserLocationId equals l.Id
                            where a.InactivatedDate.HasValue == inactive
                            select a).ToList();
            }
            else
            {
                output = (from a in context.Ads
                            join l in context.Location on a.UserLocationId equals l.Id
                            where a.InactivatedDate.HasValue == inactive &&
                            (locationLevelOrderList.Count() == 0 || locationLevelOrderList.Where(c => l.LevelOrder.StartsWith(c)).FirstOrDefault() != null)
                            select a).ToList();
            }
        }
    }

    return output;
}

Note : The methods in main GetAd that begins with Filter in name will only work with the collection (no database actions)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

故事和酒 2024-11-05 05:17:47

在您的查询中,您可以进行比较:

 ... locationIdList != null ...

由于 locationIdList 的类型为 int[],因此无法翻译查询,因为它仅支持简单比较(如错误所述) 。

您应该在查询之外而不是在查询内执行这些检查。但是,由于它们是在方法内初始化的,因此您应该确保它们已初始化并省略检查,因为这是不必要的。


我强烈建议重构整个方法和查询。这是非常长且难以理解的。将代码块移动到单独的方法中,执行您需要的一小部分,然后将它们全部放在一起。它将使您的代码更容易维护,并且更容易纠正此类错误。

Within your query, you have the comparison:

 ... locationIdList != null ...

Seeing as locationIdList is of type int[], the query cannot be translated since it only supports simple comparisons (as the error states).

You should be performing these checks outside the query, not within them. However since they are initialized within the method, you should just ensure that they are initialized and omit the check as it is unnecessary.


I would strongly recommend refactoring the whole method and the query. That is terribly long and hard to follow. Move the blocks of code into separate methods performing a small part of what you need then put them all together. It will make your code easier to maintain and correcting errors such such as this much easier.

我早已燃尽 2024-11-05 05:17:47

最后一个示例适用于 Entity Framework 4。如果出现异常,您的应用程序很可能是使用不支持 Contains 的第一个版本的 Entity Framework 构建的 .NET 3.5。

The last example works in Entity framework 4. If you get exception your application is the most probably built as .NET 3.5 with first version of Entity framework which didn't support Contains.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文