Merging Null int Column after joining - c#

I want to merge, outer join the column "Count" from View_AssessmentCount list to View_Assessment. Of course Count will get an error because it is int and I wrote String.Empty. It's at this part where I specify where to outer join the null column "Count". But then again I don't know the right terms to Google this. Please help me expound on this.
public class AssessmentWithCount
{
public int Count { get; set; }
public String AssessmentName { get; set; }
public String AssessmentInitials { get; set; }
public Int16 id { get; set; }
}
public IEnumerable<AssessmentWithCount> GetAssessmentWithCount()
{
using (var context = new SQL_TA_SCOREBOARDEntities1())
{
var query = from a in context.View_Assessment
join b in context.View_AssessmentCount on a.AssessmentName equals b.AssessmentName into ab
from subA in ab.DefaultIfEmpty()
select new AssessmentWithCount
{
AssessmentName = a.AssessmentName,
Count = (subA == null ? String.Empty : subA.Count.ToString())
};
return query;
}
}
Updated post
Now my error is "The ObjectContext instance has been disposed and can no longer be used for operations that require a connection." when I DataBind this class. :(

Don't convert the database field to a string - just use it as-is:
Count = (subA == null ? 0 : (subA.Count ?? 0))
Regarding the error message... the using statement disposes your instance of SQL_TA_SCOREBOARDEntities1, so you need to get your data now, before leaving the method:
return query.ToList();

Here try this instead:
Count = SubA.Count ?? 0
Just had some issues like these and got help. :)
Sorry I can't comment as I have less than 50 reps.

Related

Exception when using LINQ orderby: "Failed to compare two elements in the array"

Here is sample code to reproduce the exception:
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
using Microsoft.EntityFrameworkCore;
namespace Demo
{
[Keyless]
public class Contact
{
public string Name { get; set; } = default!;
public string? Address { get; set; } = default!;
public int? CCode { get; set; } = 0;
public int OtherValue { get; set; } = 0;
}
public class Foo
{
public static void Main()
{
List<Contact> raw = new();
raw.Add(new Contact { CCode = 1, Name = "Foo", Address = "Bar" });
raw.Add(new Contact { CCode = 2, Name = "Foo", Address = "Bar" });
ProcessRawResults(raw);
}
public static void ProcessRawResults(List<Contact> raw)
{
var q = from i in raw
group i by new { i.CCode, i.Name, i.Address } into g
orderby g.Key
select g;
foreach (var group in q)
{
}
}
}
}
When executing this program, an exception is thrown when execution reaches foreach (var group in q):
System.InvalidOperationException: 'Failed to compare two elements in the array.'
Inner Exception
ArgumentException: At least one object must implement IComparable
I have looked at other SO questions about this error message occurring when trying to Sort a List; but in this code I'm not sure which operation needs the comparator. It seems like the orderby g.Key operation might need to compare the anonymous class in the group, but then shouldn't the anon class have a default comparator? Or if it doesn't, I'm not sure where to put the code to implement this.
Confusingly, if I take i.CCode out of the group i by new line, then the exception doesn't happen any more.
Background: My real project is a Blazor app using EFCore 6 , and am receiving a List<Contact> from a Stored Procedure result, so it has to be [Keyless]. I have to work with the existing Stored Procedure unmodified, so am performing a transformation of the result in my code. I hope to collapse the set of results so that all entries with the same (CCode, Name, Address) result in a single row, and I'll concatenate the OtherValue into a list within that single row.
I guess it's because int? is actually Nullable<int> and Nullable<T> doesn't implement IComparable. I just tested your code but changed the grouping to this:
group i by new { CCode = i.CCode.HasValue ? i.CCode.Value : (int?)null, i.Name, i.Address } into g
and it seemed to work. It didn't throw that exception, at least.
Anonymous type do not have comparator, specify oder by properties:
var q = from i in raw
group i by new { i.CCode, i.Name, i.Address } into g
orderby g.Key.CCode, g.Key.Name, g.Key.Address
select g;

Update model sort order [duplicate]

Any idea why the LINQ OrderBy is not working in following code, (have no errors but method does not sort ...)
First my own type
public class IQLinksView
{
public int id { get; set; }
public int catid { get; set; }
public int? viewed {get;set;}
public string name {get;set;}
public string desc {get;set;}
public string url {get;set;}
public string pic {get;set;}
public string cat {get;set;}
}
then query :
IQueryable<IQLinksView> newView =
from links in this.emContext.tbl_otherlinks
select new IQLinksView { id = links.pklinkid, catid =
links.tbl_catgeory.pkcategoryid, viewed = links.linkviewed, name = links.linkname,
desc = links.linkdesc, pic = links.linkpicture, url = links.linkurl, cat =
links.tbl_catgeory.categoryname };
Untill here all fine :-), but then
newView.OrderBy(x => x.viewed);
just changes nothing,... Page is loading results showing ... but no ordering ... sniff
i have Try with (creating a comparer object ... ):
newView.OrderBy(x => (Int32)x.viewed, new CompareIntegers());
same result, no ordering ...
I do have workarounds but just wondering what is missing ....
Any suggestions will be appreciated thanks a lot :-)
Don't throw away the return value. The OrderBy extension method is does not mutate the input. Try:
newView = newView.OrderBy(x => x.viewed);
There is no reason why that won't work, assuming the viewed value is correct. Also, make sure that OrderBy is after any operations (e.g. Distinct) which will ruin ordering.
Happy coding!
No-Tracking Queries
Consider use the asnotracking() after orderby() if the result is a readonly result.
Example:
query = query.OrderByDescending(x => x.Rating).AsNoTracking();

Error when performing OrderBy on a Sub-Property of an object

I am having problem in performing OrderBy on a sub-property of an Object.
I have two separate Models as listed below:
PersonModel:
public class PersonModel
{
public string Name { get; set;}
public DeptModel Dept { get; set; }
}
DeptModel
public class DeptModel
{
public int DeptId { get; set;}
public string DeptName { get; set;}
}
I had used automapper to map the relation between those two class and I am able to retrieve data properly.
After the data had been retrieved, I am trying to implement order by using linq on the DeptName object. Then it is showing an error "Object reference not set to an instance of an object."
The result is retrieving data as IList < PersonModel >. If Debug over here it is showing the correct data at this point.
Then I am performing the OrderBy on the retrieved data and it is crashing over here.
var tmp = result.OrderBy(x => x.Dept.DeptName).ToList();
I am not sure why I getting this error. Any suggestions on resolving the issue is greatly appreciated.
You need to make sure you are not using null in a default comparison. This is a simple example:
var tmp = result.OrderBy(x => ((x.Dept == null) || (x.Dept.Deptname == null)) ? "" : x.Dept.DeptName).ToList();
If you want a really nice solution though, you should implement your own Comparator See more here:
Use own IComparer<T> with Linq OrderBy

Cannot serialize interface System.Linq.IQueryable

I'm faced with an error, "Cannot serialize interface System.Linq.IQueryable." when I try to run my method in my web service. My class is as such:
public class AirlineSearchStrong
{
public Flight_Schedule flightSchedule { get; set; }
public Flight_Schedule_Seats_and_Price flightScheduleAndPrices { get; set; }
public Airline airline { get; set; }
public Travel_Class_Capacity travelClassCapacity { get; set; }
}
[WebMethod]
public IQueryable SearchFlight(string dep_Date, string dep_Airport, string arr_Airport, int no_Of_Seats)
{
AirlineLinqDataContext db = new AirlineLinqDataContext();
var query = (from fs in db.Flight_Schedules
join fssp in db.Flight_Schedule_Seats_and_Prices on fs.flight_number equals fssp.flight_number
join al in db.Airlines on fs.airline_code equals al.airline_code
join altc in db.Travel_Class_Capacities on al.aircraft_type_code equals altc.aircraft_type_code
where fs.departure_date == Convert.ToDateTime(dep_Date)
where fs.origin_airport_code == dep_Airport
where fs.destination_airport_code == arr_Airport
where altc.seat_capacity - fssp.seats_taken >= no_Of_Seats
select new AirlineSearchStrong {
flightSchedule = fs,
flightScheduleAndPrices = fssp,
airline = al,
travelClassCapacity = altc
});
return query;
}
I've tried IQueryable, IList and returning .ToList() but most of it has turned out to be unsuccessful
i dont think
you can use Iqueryable or Ienumerable as they both do lazy execution and are not serializable. The query gets executed only when you iterate through the collection.so it doesn't make sense to return the query to the caller and asking him to iterate as his end.you need to pass a List or an Array.
You may need to change the return type to List<Type>
Hows about
public IEnumerable<AirlineSearchStrong> SearchFlight(string dep_Date, string dep_Airport, string arr_Airport, int no_Of_Seats)
{
...
return query.ToList();
}
Your trying to serialize a representation of the data, the linq query itself, instead of the data resulting from executing the query, thats why it isnt working.
You need to enumerate the linq query into an enumerable set, and serialize that.
AirlineSearchStrong might need to be marked [Serializable()]

Check if a value is in a collection with LINQ

I have a class "Employee", this has an IList<> of "TypeOfWork".
public class Employee
{
public virtual IList<TypeOfWork> TypeOfWorks { get; set; }
}
public class TypeOfWork
{
public virtual Customer Customer { get; set; }
public virtual Guid Id { get; set; }
public virtual string Name{ get; set; }
public virtual bool IsActive{ get; set; }
}
before saving, I'd lile to know if "typeofwid" (a Guid) is already in the "TypeOfWorks" collection.
I tried this :
var res = from p in employee.TypeOfWorks
where p.Id == new Guid("11111111-1111-1111-1111-111111111111")
select p ;
and tried this :
bool res = employee.TypeOfWorks.Where(f => f.Id == new Guid("11111111-1111-1111-1111-111111111111")).Count() != 0;
in the "Immediate Window" of Visual Studio but I receive the error : Expression cannot contain query expressions in both case
Do you have an idea ?
Thanks,
Just what the error says. You can't use LINQ queries in the Immediate Window because they require compilation of lambda functions. Try the first line in your actual code, where it can be compiled. :)
Also, to get this all done in one line, you can use the LINQ "Any" operator, like so:
if( ! employee.TypeOfWorks.Any(tow => tow.Id == theNewGUID) )
//save logic for TypeOfWork containing theNewGUID
How about this:
Guid guid = Guid.NewGuid("11111111-1111-1111-1111-111111111111");
var res = from p in employee.TypeOfWorks
where p.Id == guid
select p ;
The problem is constructing the guid - otherwise the linq queries should work
I think either of those work, actually. Keep in mind Visual Studio can't handle Linq Queries in the watch window either, so I suspect the error you saw is more of a Visual Studio problem than the code not working.
Try this code to get the count of typeofwork not initialized.
if(employee.TypeOfWorks
.Count(f => f.Id != new Guid("11111111-1111-1111-1111-111111111111")) != 0)
{
//do something
}

Categories