Simply put I was wondering if this is possible?
if (Descriptionsearch.Checked)
{
searchResult = searchResultBuilder(a.Description == textBox.Text))
}
else if (titleSearch.Checked)
{
searchReuslt = searchResultBuilder(a.title == textBox.Text))
}
As you can see I am simply sending a condition of a variable that has not yet been initialized but will be at the time of use.
private List<int> searchResultBuilder(Func<bool> condition)
{
foreach (var element in currentPosition.Where(a => condition()))
{
searchResults.Add(currentPosition.IndexOf(element));
}
return searchResults;
}
I simply wanted to know if there is a way to do this.
since people are asking this is the for loop from my original code
foreach(var element in main.currentPosition.Where(a => (a.key != null && main.msgSigCollection1.msgSig[(int)a.key].Description.IndexOf(searchTextBox.Text, StringComparison.OrdinalIgnoreCase) >= 0) || (a.value != null && main.msgSigCollection2.msgSig[(int)a.value].Description.IndexOf(searchTextBox.Text, StringComparison.OrdinalIgnoreCase) >= 0)))
{
searchResults.Add(main.currentPosition.IndexOf(element));
}
where currentPosition is a List<int?,int?>
You need to specify a lambda syntax to achieve what you want.
Ex: (input parameters) => expression
if(Descriptionsearch.checked == true)
searchReuslt = searchResultBuilder(a => a.Description == textBox.Text))
else if(titleSearch.checked == true)
searchReuslt = searchResultBuilder(a => a.title == textBox.Text))
MSDN
It's hard to tell based on your question, but I think what you want is to be passing lambdas, which is not what you're doing currently.
Something like this seems closer to what you want:
if(Descriptionsearch.checked == true)
searchReuslt = searchResultBuilder(a => a.Description == textBox.Text))
else if(titleSearch.checked == true)
searchReuslt = searchResultBuilder(a => a.title == textBox.Text))
private List<int> searchResultBuilder<T>(Func<T, bool> condition){
var searchResults = new List<int>();
foreach (var element in currentPosition.Where(condition))
{
searchResults.Add(currentPosition.IndexOf(element));
}
return searchResults;
}
In truth though, your question should state what you're trying to accomplish, not just how you're attempting to get there. There probably is a much easier way to accomplish everything you're trying to do here with LINQ.
Related
I need to perform a count operation on this Entity Framework (EF6) data set using a relatively complex expression as a WHERE clause and expecting it to return about 100k records.
The count operation is obviously where records are materialized and therefore the slowest of operations to take place. The count operation is taking about 10 seconds in our production environment which is unacceptable.
Note that the operation is performed on the DbSet directly (db being the Context class), so no lazy loading should be taking place.
How can I further optimize this query in order to speed up the process?
The main use case is displaying an index page with multiple filter criteria but the the function is also used for writing generic queries to the ParcelOrderstable as required for other operations in the service classes which might be a bad idea resulting in very complex queries resulting from laziness and might potentially be a future problem.
The count is later used for pagination, and a much smaller number of records (e.g. 500) is actually displayed. This is a database-first project using SQL Server.
ParcelOrderSearchModel is a C#-class that serves to encapsualte query parameters and is used exclusively by service classes in order to call the GetMatchingOrdersfunction.
Note that on the majority of calls, the majority of the parameters of ParcelOrderSearchModel will be null.
public List<ParcelOrderDto> GetMatchingOrders(ParcelOrderSearchModel searchModel)
{
// cryptic id known --> allow public access without login
if (String.IsNullOrEmpty(searchModel.KeyApplicationUserId) && searchModel.ExactKey_CrypticID == null)
throw new UnableToCheckPrivilegesException();
Func<ParcelOrder, bool> userPrivilegeValidation = (x => false);
if (searchModel.ExactKey_CrypticID != null)
{
userPrivilegeValidation = (x => true);
}
else if (searchModel.KeyApplicationUserId != null)
userPrivilegeValidation = privilegeService.UserPrivilegeValdationExpression(searchModel.KeyApplicationUserId);
var criteriaMatchValidation = CriteriaMatchValidationExpression(searchModel);
var parcelOrdersWithNoteHistoryPoints = db.HistoryPoint.Where(hp => hp.Type == (int)HistoryPointType.Note)
.Select(hp => hp.ParcelOrderID)
.Distinct();
Func<ParcelOrder, bool> completeExpression = order => userPrivilegeValidation(order) && criteriaMatchValidation(order);
searchModel.PaginationTotalCount = db.ParcelOrder.Count(completeExpression);
// todo: use this count for pagination
}
public Func<ParcelOrder, bool> CriteriaMatchValidationExpression(ParcelOrderSearchModel searchModel)
{
Func<ParcelOrder, bool> expression =
po => po.ID == 1;
expression =
po =>
(searchModel.KeyUploadID == null || po.UploadID == searchModel.KeyUploadID)
&& (searchModel.KeyCustomerID == null || po.CustomerID == searchModel.KeyCustomerID)
&& (searchModel.KeyContainingVendorProvidedId == null || (po.VendorProvidedID != null && searchModel.KeyContainingVendorProvidedId.Contains(po.VendorProvidedID)))
&& (searchModel.ExactKeyReferenceNumber == null || (po.CustomerID + "-" + po.ReferenceNumber) == searchModel.ExactKeyReferenceNumber)
&& (searchModel.ExactKey_CrypticID == null || po.CrypticID == searchModel.ExactKey_CrypticID)
&& (searchModel.ContainsKey_ReferenceNumber == null || (po.CustomerID + "-" + po.ReferenceNumber).Contains(searchModel.ContainsKey_ReferenceNumber))
&& (searchModel.OrKey_Referencenumber_ConsignmentID == null ||
((po.CustomerID + "-" + po.ReferenceNumber).Contains(searchModel.OrKey_Referencenumber_ConsignmentID)
|| (po.VendorProvidedID != null && po.VendorProvidedID.Contains(searchModel.OrKey_Referencenumber_ConsignmentID))))
&& (searchModel.KeyClientName == null || po.Parcel.Name.ToUpper().Contains(searchModel.KeyClientName.ToUpper()))
&& (searchModel.KeyCountries == null || searchModel.KeyCountries.Contains(po.Parcel.City.Country))
&& (searchModel.KeyOrderStates == null || searchModel.KeyOrderStates.Contains(po.State.Value))
&& (searchModel.KeyFromDateRegisteredToOTS == null || po.DateRegisteredToOTS > searchModel.KeyFromDateRegisteredToOTS)
&& (searchModel.KeyToDateRegisteredToOTS == null || po.DateRegisteredToOTS < searchModel.KeyToDateRegisteredToOTS)
&& (searchModel.KeyFromDateDeliveredToVendor == null || po.DateRegisteredToVendor > searchModel.KeyFromDateDeliveredToVendor)
&& (searchModel.KeyToDateDeliveredToVendor == null || po.DateRegisteredToVendor < searchModel.KeyToDateDeliveredToVendor);
return expression;
}
public Func<ParcelOrder, bool> UserPrivilegeValdationExpression(string userId)
{
var roles = GetRolesForUser(userId);
Func<ParcelOrder, bool> expression =
po => po.ID == 1;
if (roles != null)
{
if (roles.Contains("ParcelAdministrator"))
expression =
po => true;
else if (roles.Contains("RegionalAdministrator"))
{
var user = db.AspNetUsers.First(u => u.Id == userId);
if (user.RegionalAdministrator != null)
{
expression =
po => po.HubID == user.RegionalAdministrator.HubID;
}
}
else if (roles.Contains("Customer"))
{
var customerID = db.AspNetUsers.First(u => u.Id == userId).CustomerID;
expression =
po => po.CustomerID == customerID;
}
else
{
expression =
po => false;
}
}
return expression;
}
If you can possibly avoid it, don't count for pagination. Just return the first page. It's always expensive to count and adds little to the user experience.
And in any case you're building the dynamic search wrong.
You're calling IEnumerable.Count(Func<ParcelOrder,bool>), which will force client-side evaluation where you should be calling IQueryable.Count(Expression<Func<ParcelOrder,bool>>). Here:
Func<ParcelOrder, bool> completeExpression = order => userPrivilegeValidation(order) && criteriaMatchValidation(order);
searchModel.PaginationTotalCount = db.ParcelOrder.Count(completeExpression);
But there's a simpler, better pattern for this in EF: just conditionally add criteria to your IQueryable.
eg put a method on your DbContext like this:
public IQueryable<ParcelOrder> SearchParcels(ParcelOrderSearchModel searchModel)
{
var q = this.ParcelOrders();
if (searchModel.KeyUploadID != null)
{
q = q.Where( po => po.UploadID == searchModel.KeyUploadID );
}
if (searchModel.KeyCustomerID != null)
{
q = q.Where( po.CustomerID == searchModel.KeyCustomerID );
}
//. . .
return q;
}
I just wonder if it's possible to make it better (and I guess there are many, many better ways to do it). So the question is how to return true if in my list are 4 types of components. My list may contain 1000 of them , but I just need to return true if there are 4 objects of different types (CPU, GPU, RAM, PowerSupply). These objects are children of abstract class Component and contain property of enum type.
public bool IsWorking()
{
bool hasCPU = AllComponents.Any(component => component.CompType == ComponentsType.CPU);
bool hasGPU = AllComponents.Any(component => component.CompType == ComponentsType.GPU);
bool hasPowerSupply = AllComponents.Any(component => component.CompType == ComponentsType.PowerSupply);
bool hasRAM = AllComponents.Any(component => component.CompType == ComponentsType.RAM);
bool? hasAllNeededComp // JUST WONDERING HOW TO MAKE IT BETTER
}
It depends on what you mean by "better". But if you want to make this as fast as possible, you should just use a foreach loop like this:
public bool IsWorking()
{
bool hasCPU = false;
bool hasGPU = false;
bool hasPowerSupply = false;
bool hasRAM = false;
foreach(var component in AllComponents)
{
if(component.CompType == ComponentsType.CPU) hasCPU = true;
else if(component.CompType == ComponentsType.GPU) hasGPU = true;
else if(component.CompType == ComponentsType.PowerSupply) hasPowerSupply = true;
else if(component.CompType == ComponentsType.RAM) hasRAM = true;
if(hasCPU && hasGPU && hasPowerSupply && hasRAM) return true;
}
return false;
}
Not as fancy as some of these other solutions, but this will at most iterate through the list once.
Funny linq query :
new [] { ComponentsType.CPU, ComponentsType.GPU, ComponentsType.PowerSupply, ComponentsType.RAM }
.Except(AllComponents.Select(component => component.CompType))
.Any() == false;
You can group by CompType to get distinct ones, then add a where clause including all the needed components and count the result :
AllComponents.GroupBy(c => c.CompType)
.Select(c => c.Key)
.Where(c => c == ComponentsType.CPU
|| c == ComponentsType.GPU
|| c == ComponentsType.PowerSupply
|| c == ComponentsType.RAM)
.Count() == 4;
To be a bit cleaner, you can list the needed components and use Contains() :
var requirements = new List<ComponentsType>
{
ComponentsType.CPU,
ComponentsType.GPU,
ComponentsType.PowerSupply,
ComponentsType.RAM
};
return AllComponents.GroupBy(c => c.CompType)
.Select(c => c.Key)
.Where(c => requirements.Contains(c))
.Count() == 4;
I think it is readable:
public bool IsWorking()
{
return AllComponents.Any(component => component.CompType == ComponentsType.CPU)
&& AllComponents.Any(component => component.CompType == ComponentsType.GPU)
&& AllComponents.Any(component => component.CompType == ComponentsType.PowerSupply)
&& AllComponents.Any(component => component.CompType == ComponentsType.RAM);
}
A more simpler code:
public bool IsWorking()
{
ComponentsType[] requiredComps = new[] { ComponentsType.CPU, ComponentsType.GPU, ComponentsType.PowerSupply, ComponentsType.RAM };
foreach (var requiredComp in requiredComps)
{
if (!AllComponents.Any(component => component.CompType == requiredComp))
return false;
}
return true;
}
At the moment I get the number of possible combinations (Factorial of the number of check-boxes) and write that many if statements, something like:
Assuming I have 3 check-boxes:
if (IncludeIncomingCalls && !IncludeOutgoingCalls && !IncludeExternalCalls)
{
return _callsData.Where(x => x.IncomingCall && !x.OutgoingCall && !x.ExternalCall);
}
if (!IncludeIncomingCalls && IncludeOutgoingCalls && !IncludeExternalCalls)
{
return _callsData.Where(x => !x.IncomingCall && x.OutgoingCall && !x.ExternalCall);
}
if (!IncludeIncomingCalls && !IncludeOutgoingCalls && IncludeExternalCalls)
{
return _callsData.Where(x => !x.IncomingCall && !x.OutgoingCall && x.ExternalCall);
}
if (IncludeIncomingCalls && IncludeOutgoingCalls && !IncludeExternalCalls)
{
return _callsData.Where(x => x.IncomingCall && x.OutgoingCall && !x.ExternalCall);
}
if (IncludeIncomingCalls && !IncludeOutgoingCalls && IncludeExternalCalls)
{
return _callsData.Where(x => x.IncomingCall && !x.OutgoingCall && x.ExternalCall);
}
if (!IncludeIncomingCalls && IncludeOutgoingCalls && IncludeExternalCalls)
{
return _callsData.Where(x => !x.IncomingCall && x.OutgoingCall && x.ExternalCall);
}
Even though this will meet the requirement I don't see it as an optimal solution considering that the number of check-boxes might increase in the future and the number of the combinations could get massive.
I was wandering if there is a known pattern when it comes to filtering lists based on selected check-boxes?
Compare the Boolean value with each field.
Try this:
return _callsData.Where(x => x.IncomingCall == IncludeIncomingCalls && x.OutgoingCall == IncludeOutgoingCalls && x.ExternalCall== IncludeExternalCalls);
Try this :
return _callsData.Where(x => x.IncomingCall==IncludeIncomingCalls && x.OutgoingCall==IncludeOutgoingCalls && x.ExternalCall==IncludeExternalCalls);
Note that you can compose the IQueryable. You can add additional Where clauses as needed.
var result = callsData.Select(x => x);
if (IncludeIncomingCalls) {
result = result.Where(x => x.IncomingCall);
}
else {
result = result.Where(x => !x.IncomingCall);
}
if (IncludeOutgoingCalls) {
result = result.Where(x => x.OutgoingCall);
}
else {
result = result.Where(x => !x.OutgoingCall);
}
if (IncludeExternalCalls) {
result = result.Where(x => x.ExternalCall);
}
else {
result = result.Where(x => !x.ExternalCall);
}
return result;
I just show this as a general pattern. For your usecase, the solution of Ubiquitous Developers is easier to read and understand.
But if the condition is more complex than just a bit flag, this pattern might come in handy. Just as an example:
if (ShowOnlyActive) {
result = result.Where(x => x.State == CallState.Active);
}
else {
result = result.Where(x => x.State == CallState.Deleted || x.State == CallState.Inactive);
}
Off topic, just to further illustrate this general concept: adding additional clauses to an IQueryable can be used to refactor parts of a query to helper or extension methods, for example to implement paging.
public interface IPageableQuery {
// The page size (i.e. the number of elements to be displayed).
// The method processing the Query will Take() this number of elements.
int DisplayLength { get; set; }
// The number of elements that have already been displayed.
// The method processing the Query will Skip() over these elements.
int DisplayStart { get; set; }
}
public static IQueryable<T> ApplyPaging<T>(this IQueryable<T> entries, IPageableQuery query)
where T : class {
if (query.DisplayStart >= 0 && query.DisplayLength > 0) {
return entries.Skip(query.DisplayStart).Take(query.DisplayLength);
}
return entries;
}
You could use the following pattern:
//some checkboxes
CheckBox chkA = ...
CheckBox chkB = ...
CheckBox chkC = ...
//build up your filters
var filters = new List<Predicate<SomeEntity>>();
filters.Add(e => chkA.Checked && e.IsA);
filters.Add(e => chkB.Checked && e.IsB);
filters.Add(e => chkC.Checked && e.IsC);
//And now simply apply the filters
var entities = ... //some enumerable of SomeEntity
var filteredEntities = entities.Where(e => filters.All(filter => filter(e)));
Note that this will only work correctly if IsA, IsB and IsC are excluding conditions, but this seems to be the set up you currently have.
I have a foreach loop with some results from a linq query. I am trying to get it to run faster (it's taking about an hour to run) but when I convert to Parallel.foreach, the results I get are different that when I run with the standard foreach, even though it cuts the time in half. Can those of you who are much better at linq and parallelism help me out some on this.
Really would like some way to speed it up. I'm a bit confused though why the parallel.foreach is not giving me the same results. Maybe someone smarter than I can fill me in.
The standard foreach:
var studentTestGroup = from st in this
group st by new { st.TestName, st.STI }
into studentGroups
select new { TestName = studentGroups.Key.TestName, STI = studentGroups.Key.STI, students = studentGroups };
//Loop through each group that has more than one test, or where there exists any retests at all.
foreach (var studentGroup in studentTestGroup.Where(t => t.students.Count() > 1 || t.students.Any(x => x.Retest == "Y")))
{
if (studentGroup.students.Any(t => t.Retest == "Y") && studentGroup.students.Count(t => t.Retest == "N" || t.Retest == "") == 1)
{
//For a test name and STI, if there exists a restest and only 1 non-retest, keep highest and disacrd the rest
var studentToKeep = studentGroup.students.OrderByDescending(t => t.TestScaledScore).First();
this.RemoveAll(t => t.STI == studentGroup.STI && t.TestName == studentGroup.TestName && t.PrimaryKey != studentToKeep.PrimaryKey);
}
else if (studentGroup.students.Any(t => t.Retest == "Y") && studentGroup.students.Count(t => t.Retest == "N" || t.Retest == "") > 1)
{
//For a test anem and STI, if there exists a restest and more than 1 non-retest,
//then keep the highest (number of non-retests) scores and discard the rest
int numRetests = studentGroup.students.Count(t => t.Retest == "N" || t.Retest == "");
var studentsToKeep = studentGroup.students.OrderByDescending(t => t.TestScaledScore).Take(numRetests);
this.RemoveAll(t => t.STI == studentGroup.STI && t.TestName == studentGroup.TestName && !studentsToKeep.Any(x => x.PrimaryKey == t.PrimaryKey));
}
else if (studentGroup.students.Any(t => t.Retest == "Y") && !studentGroup.students.Any(t => t.Retest == "N" || t.Retest == ""))
{
this.RemoveAll(t => t.STI == studentGroup.STI && t.TestName == studentGroup.TestName && Convert.ToInt32(t.TestScaledScore) < 400);
}
}
The part where I converted to a parallel foreach:
Parallel.ForEach (studentTestGroup.AsParallel().Where(t => t.students.Count() > 1 || t.students.Any(x => x.Retest == "Y")).AsParallel(), studentGroup =>
{
Do not combine PLinq(AsParallel) and TPL(Parallel.ForEach). That will even decrease speed because you overload thread pool. Use one of technics. All you can get from parallelism is speed up in your CPU cores count. After that you can use some profilers. Or heuristics about collections that only you know.
For the code you provided - do not duplicate instructions! For example:
studentGroup.students.Count(t => t.Retest == "N" || t.Retest == "")
you can calculate it only once instead of every-time in all different conditions.
Same goes to:
studentGroup.students.Any(t => t.Retest == "Y")
"Any" will iterate your entire collection till predicate match, so just not iterate large collections multiple times for all if-statements with the same condition!
Question yourself about collections, maybe you could use dictionaries for search items or some other structures, but as I said that would be more like heuristics for your collections that maybe provide some speed up.
Hope this helps.
If you want more then you need profilers.
What is type is this?
I think there is a race condition on this.RemoveAll(). If you modify a list/collection in multiple threads at the same time the result of the operation on the collection isn't clear.
In this case you could use a lock statement around your RemoveAll()-calls, but then the benefit of your parallel foreach would be gone.
Another possibility could be to remember all items which should be removed and remove them after the foreach. I think an add-operation on a collection should be possible on multiple threads.
Edit:
This may could be a faster implementation to remove the specified items:
List itemsToRemove = new List();
foreach (var studentGroup in studentTestGroup.Where(t => t.students.Count() > 1 || t.students.Any(x => x.Retest == "Y")))
{
int countNo = studentGroup.students.Count(t => t.Retest == "N" || t.Retest == "");
bool anyYes = studentGroup.students.Any(t => t.Retest == "Y");
if (anyYes && countNo == 1)
{
var studentToKeep = studentGroup.students.Single(t => t.Retest == "N" || t.Retest == "");
itemsToRemove.AddRange(t => t.STI == studentGroup.STI && t.TestName == studentGroup.TestName && t.PrimaryKey != studentToKeep.PrimaryKey);
}
else if (anyYes && countNo > 1)
{
var studentsToKeep = studentGroup.students.Where(t => t.Retest == "N" || t.Retest == "");
itemsToRemove.AddRange(t => t.STI == studentGroup.STI && t.TestName == studentGroup.TestName && !studentsToKeep.Any(x => x.PrimaryKey == t.PrimaryKey));
}
else if (anyYes && countNo == 0)
{
itemsToRemove.AddRange(t => t.STI == studentGroup.STI && t.TestName == studentGroup.TestName && Convert.ToInt32(t.TestScaledScore) < 400);
}
}
foreach (var itemToRemove in itemsToRemove)
{
this.Remove(itemToRemove);
}
I am filtering a collection and I perform 2 filters that are the same but for different fields.
There must be a way I can reduce the duplication of code here?
The checks are whether a date has been entered, and whether it is before a cut off date entered by the user.
public override IList<Company> Search()
{
var list = CacheObjects.Subcontractors;
this.ApplicationFormReturnedCheck(ref list);
this.ApplicationFormSentCheck(ref list);
}
private void ApplicationFormReturnedCheck(ref IList<Subcontractor> list)
{
if (this.ApplicationFormNotReturnedFlag == true && this.ApplicationFormReturned != null)
{
list =
list.Where(x => x.ApplicationFormReturned == null || x.ApplicationFormReturned < this.ApplicationFormReturned).ToList();
}
else if (this.ApplicationFormNotReturnedFlag == true)
{
list = list.Where(x => x.ApplicationFormReturned == null).ToList();
}
else if (this.ApplicationFormReturned != null)
{
list = list.Where(x => x.ApplicationFormReturned < this.ApplicationFormReturned).ToList();
}
}
private void ApplicationFormSentCheck(ref IList<Subcontractor> list)
{
if (this.ApplicationFormNotSentFlag == true && this.ApplicationFormSent != null)
{
list =
list.Where(x => x.ApplicationFormSent == null || x.ApplicationFormSent < this.ApplicationFormSent).ToList();
}
else if (this.ApplicationFormNotSentFlag == true)
{
list = list.Where(x => x.ApplicationFormSent == null).ToList();
}
else if (this.ApplicationFormSent != null)
{
list = list.Where(x => x.ApplicationFormSent < this.ApplicationFormSent).ToList();
}
}
I would suggest you can do something as simple as have some instances of Func<Subcontractor,bool> which cover your various scenarios. This is the type of Func that the Where method expects
To demonstrate let me take one of your methods and show you how:
private void ApplicationFormReturnedCheck(ref IList<Subcontractor> list)
{
var isFormReturned = new Func<Subcontractor,bool>(
x => x.ApplicationFormReturned != null);
var isBeforeDate = new Func<Subcontractor,bool>(
x => x.ApplicationFormReturned < this.ApplicationFormReturned);
var isFormReturnedOrBeforeDate= new Func<Subcontractor,bool>(
x => isFormReturned(x) || isFormReturnedBeforeDate(x));
if (this.ApplicationFormNotReturnedFlag == true && this.ApplicationFormReturned != null)
{
list = list.Where(isFormReturnedOrBeforeDate).ToList();
}
else if (this.ApplicationFormNotReturnedFlag == true)
{
list = list.Where(isFormReturned).ToList();
}
else if (this.ApplicationFormReturned != null)
{
list = list.Where(isBeforeDate).ToList();
}
}
The other method you've shown, although having similar logic, uses a different set of variables. (ApplicationFormSent in place of ApplicationFormReturned). The way I see it you have two options
Duplicate the above within the other method, using the differing variable names
Use a more complex method whereby you have these 3 Func's outside of the scope of each method, and able to distinguish which variables (*Sent or *Returned) to use.
The problem with 2. above is that as your perceved "reuse" goes up, the readability of your code goes down.
In all honesty, I see no major problem with your original code! Its clear, its pretty concise and its easy to see what it's doing. By wrapping all this logic up with predicates (which could conceivably be elsewhere in the class), you're making it harder to read and harder to maintain.
A Func(T, TResult) can be used to encapsulate common predicate methods. In your case, the Func would need to be initilialized in the constructor since you are using instance members in the filter. Ex:
private readonly Func<Subcontractor, bool> _pred;
public Subcontractor()
{
_pred = x => x.ApplicationFormReturned == null || x.ApplicationFormReturned < this.ApplicationFormReturned;
}
private void ApplicationFormReturnedCheck( ref IList<Subcontractor> list )
{
if( this.ApplicationFormNotReturnedFlag == true && this.ApplicationFormReturned != null )
{
list = list.Where( _pred ).ToList();
}
else if( this.ApplicationFormNotReturnedFlag == true )
{
list = list.Where( x => x.ApplicationFormReturned == null ).ToList();
}
else if( this.ApplicationFormReturned != null )
{
list = list.Where( x => x.ApplicationFormReturned < this.ApplicationFormReturned ).ToList();
}
}