简体   繁体   中英

Filter dataset in repository design pattern C#

I have a given below query, which is perfect

SELECT
    MAX(WarehouseId)       AS WareHouseId, 
    MAX(CompanyId)         AS CompanyId, 
    MAX(ProductId)         AS ProductId,
    SUM(AvailableQuantity) AS AvailableQuantity,
    PurchaseItemPrice 
FROM
    PurchaseItem 
WHERE
    CompanyId = 1 
GROUP BY
    PurchaseItemPrice
ORDER BY
    MAX(ProductId) ASC

Which I needs to convert into given below format instead of linq. I really don't know what is the name of given below format. Please also tell me what we can call this format and if this is not a good approach to get data please suggest something better because I'm new to repository design pattern.

unitOfWork.PurchaseItemRepository.DataSet
    .Where( x => x.CompanyId == id )
    .ToList()
    .GroupBy( x => x.PurchaseItemPrice )
    .Select( x =>
        x.Max( y => new
        {
            y.WarehouseId,
            y.CompanyId,
            y.ProductId,
            y.AvailableQuantity
        } )
    );

public IRepository<PurchaseItem> PurchaseItemRepository
{
    get
    {
        if (_PurchaseItemRepository == null)
        {
            dbContext.Configuration.ProxyCreationEnabled = false;
            _PurchaseItemRepository = new Repository<PurchaseItem>(dbContext);
        }
        return _PurchaseItemRepository;
    }
}

And ProductItem is an Entity

Moreover, when I executed above code, It will display given below error.

An exception of type 'System.ArgumentException' occurred in mscorlib.dll but was not handled in user code. Additional information: At least one object must implement IComparable.

You need to have a way to determine the max. What are you doing max on how is the compiler going to know what property you want to use max on?

you probably want to grab the MAX on each one of those properties individually. Ie

 unitOfWork.PurchaseItemRepository.DataSet
      .Where(x => x.CompanyId == id).ToList()
      .GroupBy(x => x.PurchaseItemPrice)
      .Select(x => new {
        WarehouseId = x.OrderByDescending(v => v.WarehouseId).FirstOrDefault(),
        CompanyId = x.OrderByDescending(v => v.CompanyId).FirstOrDefault(),
        //Do the rest here 
      }).OrderBy( output => output.ProductId )
      .ToList();

As a side note you probably shouldn't be calling ToList() this will materialize the whole table. You should work with IQuerables instead so you can filter without pulling the whole table

(BTW, you do not need to use the Repository (anti-)pattern with Linq and Entity Framework because the DbContext is the repository. Note that creating classes to hold predefined Linq queries is not the same thing as a Repository. I'm also not convinced that the Unit-of-Work Pattern is of much use with Entity Framework either as a short-lived DbContext in a using block with a Transaction also fulfils that role)

var list = dbContext.PurchaseItems
    .Where( x => x.CompanyId == 1 )
    .GroupBy( x => x.PurchaseItemPrice )
    .Select( grp => new {
        PurchaseItemPrice = grp.Key,
        WarehouseId       = grp.Max( x => x.WarehouseId ),
        CompanyId         = grp.Max( x => x.CompanyId ),
        ProductId         = grp.Max( x => x.ProductId ),
        AvailableQuantity = grp.Sum( x => x.AvailableQuantity ),
    } )
    .OrderBy( output => output.ProductId )
    .ToList();

list will need to use inferred type ( var ) because of the use of an anonymous-type in the .Select call. If you change it to a custom record-type then you can use List<MyOutputRecordType> instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM