I am trying to return a Guid value below. However the database(and my dbml) has that column as a nullable Guid
and it is generating an exception on the .Select
portion saying it can't convert from an IQueryable<System.Guid?>
to a System.Guid
.
I am guessing I need to make my return value "concrete" first???? True?
If so how do I do that with Guid's?public static Guid GetCurrentWorkerByType(int enrollmentID, int staffTypeID)
{
using (var context = CmoDataContext.Create())
{
IQueryable<tblWorkerHistory> tWorkHist = context.GetTable<tblWorkerHistory>();
return (tWorkHist.Where(workHist =>
(workHist.EnrollmentID == enrollmentID) &&
(workHist.tblStaff.StaffTypeID == staffTypeID) &&
(workHist.EndDate == null || workHist.E开发者_如何学PythonndDate > DateTime.Now))
.Select(workHist => workHist.Worker));
}
}
}
// Get the Guid? itself, for sake of example from IQueryable<Guid?>
// (could be `null` from DB value or because queryable was empty)
Guid? maybeGuid = queryable.FirstOrDefault();
// Need to have *a* GUID or default it to something
// because a Guid is a value-type and needs *a* value.
Guid theGuid = maybeGuid ?? Guid.Empty;
Also see Nullable<T>.HasValue/Value
-- A longer, but equivalent, method would be:
Guid theGuid = maybeGuid.HasValue ? maybeGuid.Value : Guid.Empty;
Observe that HasValue
may be suitable in general if
statements to change logic and also note that Value
will throw an exception if maybeGuid is "has no value" -- is null
-- which is why the guard is required.
Happy coding.
Pedantic detail: The equivalent method is not "thread safe". That is, assuming maybeGuid
was shared, it could be assigned null
between HasValue
and Value
. There are a number of SO questions that cover the "thread safety" of ??
(the coalesce operator) -- the generated IL effectively uses a temporary variable so the value may be stale but an exception can't be thrown.
Use
.Select(workHist => workHist.Worker).Single();
.Select()
returns a query that has not run.- If you use
.Select().ToList()
then you you return a list. - If you use
.Select().Single()
then you return one item and it makes sure only one item is there - If you use
.Select().SingleOrDefault()
then you return one item and default. Query must not contain more than 1 item. - If you use
.Select().First()
then you return the first item. Query must contain at least 1 item. - If you use
.Select().FirstOrDefault()
then you return the first item or default. Query can contain 1 or more or no items.
Try
Change your return type from System.Guid to ?System.Guid // nullable of guid
Then add .FirstOrDefault() after the select call
A struct cannot be null, but the System.Nullable class wraps the struct in a class.
What you've got is a query that hasn't executed for one, and for two, it will return a list of Guids as far as I can tell. If you want to return the first Guid or default (which I believe is a zero'd out guid) you can say .FirstorDefault() after your select.
The closest you will get representing null
with a Guid
is to use Guid.Empty
. So, for your query, you will probably want to first pick the value returned by FirstOrDefault
, make a null check, and then return a reasnable value:
Guid? result = tWorkHist.Where(workHist =>
(workHist.EnrollmentID == enrollmentID)
&& (workHist.tblStaff.StaffTypeID == staffTypeID)
&& (workHist.EndDate == null || workHist.EndDate > DateTime.Now))
.Select(workHist => workHist.Worker)
.FirstOrDefault();
return result.HasValue ? result.Value : Guid.Empty;
Use FirstOrDefault with conjunticon with Guid.Empty
Try this:
public static Guid GetCurrentWorkerByType(int enrollmentID, int staffTypeID)
{
using (var context = CmoDataContext.Create())
{
IQueryable<tblWorkerHistory> tWorkHist = context.GetTable<tblWorkerHistory>();
var guid = (tWorkHist.Where(workHist => (workHist.EnrollmentID == enrollmentID) &&
(workHist.tblStaff.StaffTypeID == staffTypeID) &&(workHist.EndDate == null || workHist.EndDate > DateTime.Now))
.Select(workHist => workHist.Worker)
///####NOTICE THE USE OF FirstOrDefault
).FirstOrDefault();
return (guid.HasValue)?guid.Value:Guid.Empty
}
}
精彩评论