I have a Linq2Sql query that looks like this:
var data = from d in dc.GAMEs
where (d.GAMEDATE + d.GAMETIME.Value.TimeOfDay) >= DateTime.Now
&& d.GAMESTAT == 'O' && d.GAMETYPE == 0 select d;
Resharper is underlining the "d.GAMETIME.Value.TimeOfDay" in blue and telling me it's a possible System.InvalidOperationException. While I get that if it were C# code, referencing Value without checking if it has a value would be such, i'm not sure if that is true of a Linq query.
The actual SQL generated looks horrendous, and makes me want to burn my eyes out, but I see nothing that looks like it could be a null reference. Can I safely ignore this?
(ignore for the moment the other issues, such as if it returns the expected results)
EDIT:
Upon further thought, I can see how the above might cause an exception in a LinqToObjects query, and possibly other kinds (XML?). So yeah, I suppose Resharper is just being safe.
When dealing with expression trees (as this LINQ to SQL query) it totally depends on the LINQ provider used (in your case LINQ to SQL). Therefore, it is (almost) impossible for Resharper to say anything useful about your query. I think it just interprets this code as normal C# delegates. I would say it is safe to ignore, but perhaps add a comment for the next developer.
Without seeing the data schema my guess is that GAMETIME is Nullable<DateTime> - i.e. maps to datetime/time field in the DB that can be null. Resharper is simply giving you a static analysis warning that you are referencing Nullable<T>.Value without checking that it has a value.
You can rewrite the query in this way:
var data = from d in dc.GAMEs
where (d.GAMEDATE + (d.GAMETIME.HasValue ? d.GAMETIME.TimeOfDay : new TimeSpan())) >= DateTime.Now
&& d.GAMESTAT == 'O' && d.GAMETYPE == 0 select d;
The above query will just use a TimeSpan of 0 when GAMETIME is NULL.
Considering that GAMEDATE is a non-nullable database field and GAMETIME is a nullable one, I recommend that you make GAMETIME non-nullable too. This way the two fields are consistent and do not need extra logic to handle NULL values.
EDIT I have just confirmed that trying to call Nullable<T>.Value does indeed throw InvalidOperationException, not NullReferenceException.
From the horse's mouth (bolding is mine):
The two fundamental members of the
Nullable structure are the HasValue
and Value properties. If the HasValue
property for a Nullable object is
true, the value of the object can be
accessed with the Value property. If
the HasValue property is false, the
value of the object is undefined and
an attempt to access the Value
property throws an
InvalidOperationException.
Related
When you query an EntitySet property on a model object in Linq-to-SQL, it returns all rows from the entityset and does any further querying client-side.
This is confirmed in a few places online and I've observed the behavior myself. The EntitySet does not implement IQueryable.
What I've had to do is convert code like:
var myChild = ... ;
// Where clause performed client-side.
var query = myChild.Parents().Where(...) ;
to:
var myChild = ... ;
// Where clause performed in DB and only minimal set of rows returned.
var query = MyDataContext.Parents().Where(p => p.Child() == myChild) ;
Does anyone know a better solution?
A secondary question: is this fixed in the Entity Framework?
An EntitySet is just a collection of entities. It implements IEnumerable, not IQueryable. The Active Record pattern specifies that entities be directly responsible for their own persistence. OR mapper entities don't have any direct knowledge of the persistence layer. OR Mappers place this responsibility, along with Unit Of Work, and Identity Map responsibilities into the Data Context. So if you need to query the data source, you gotta use the context (or a Table object). To change this would bend the patterns in use.
I had a similar problem: How can I make this SelectMany use a join. After messing with LINQPad for a good amount of time I found a decent workaround. The key is to push the EntitySet you are looking at inside a SelectMany, Select, Where, etc. Once it's inside that it becomes an Expression and then the provider can turn it into a proper query.
Using your example try this:
var query = from c in Children
where c == myChild
from p in c.Parents
where p.Age > 35
select p;
I'm not able to 100% verify this query as I don't know the rest of your model. But the first two lines of the query cause the rest of it to become an Expression that the provider turns into a join. This does work with my own example that is on the question linked to above.
If I have a LINQ to SQL table that has a field called say Alias.
There is then a method stub called OnAliasChanging(string value);
What I want to do is to grab the value, check the database whether the value already exists and then set the value to the already entered value.
So I may be changing my alias from "griegs" to "slappy" and if slappy exists then I want to revert to the already existing value of "griegs".
So I have;
partial void OnaliasChanging(string value)
{
string prevValue = this.alias;
this.Changed = true;
}
When I check the value of prevValue it's always null.
How can I get the current value of a field?
Update
If I implement something like;
partial void OnaliasChanging(string value)
{
if (this.alias != null)
this.alias = "TEST VALUE";
}
it goes into an infinte loop which is unhealthy.
If I include a check to see whether alias already == "TEST VALUE" the infinate loop still remains as the value is always the original value.
Is there a way to do this?
The code snippets you've posted don't lend themselves to any plausible explanation of why you'd end up with an infinite loop. I'm thinking that this.alias might be a property, as opposed to a field as the character casing would imply, but would need to see more. If it is a property, then you are invoking the OnAliasChanging method before the property is ever set; therefore, trying to set it again in the same method will always cause an infinite loop. Normally the way to design this scenario is to either implement a Cancel property in your OnXyzChanging EventArgs derivative, or save the old value in the OnXyzChanging method and subsequently perform the check/rollback in the OnXyzChanged method if you can't use the first (better) option.
Fundamentally, though, what you're trying to do is not very good design in general and goes against the principles of Linq to SQL specifically. A Linq to SQL entity is supposed to be a POCO with no awareness of sibling entities or the underlying database at all. To perform a dupe-check on every property change not only requires access to the DataContext or SqlConnection, but also causes what could technically be called a side-effect (opening up a new database connection and/or silently discarding the property change). This kind of design just screams for mysterious crashes down the road.
In fact, your particular scenario is one of the main reasons why the DataContext class was made extensible in the first place. This type of operation belongs in there. Let's say that the entity here is called User with table Users.
partial class MyDataContext
{
public bool ChangeAlias(Guid userID, string newAlias)
{
User userToChange = Users.FirstOrDefault(u => u.ID == userID);
if ((userToChange == null) || Users.Any(u => u.Alias == newAlias))
{
return false;
}
userToChange.Alias = newAlias;
// Optional - remove if consumer will make additional changes
SubmitChanges();
return true;
}
}
This encapsulates the operation you want to perform, but doesn't prevent consumers from changing the Alias property directly. If you can live with this, I would stop right there - you should still have a UNIQUE constraint in your database itself, so this method can simply be documented and used as a safe way to attempt a name-change without risking a constraint violation later on (although there is always some risk - you can still have a race condition unless you put this all into a transaction or stored procedure).
If you absolutely must limit access to the underlying property, one way to do this is to hide the original property and make a read-only wrapper. In the Linq designer, click on the Alias property, and on the property sheet, change the Access to Internal and the Name to AliasInternal (but don't touch the Source!). Finally, create a partial class for the entity (I would do this in the same file as the MyDataContext partial class) and write a read-only wrapper for the property:
partial class User
{
public string Alias
{
get { return AliasInternal; }
}
}
You'll also have to update the Alias references in our ChangeAlias method to AliasInternal.
Be aware that this may break queries that try to filter/group on the new Alias wrapper (I believe Linq will complain that it can't find a SQL mapping). The property itself will work fine as an accessor, but if you need to perform lookups on the Alias then you will likely need another GetUserByAlias helper method in MyDataContext, one which can perform the "real" query on AliasInternal.
Things start to get a little dicey when you decide you want to mess with the data-access logic of Linq in addition to the domain logic, which is why I recommend above that you just leave the Alias property alone and document its usage appropriately. Linq is designed around optimistic concurrency; typically when you need to enforce a UNIQUE constraint in your application, you wait until the changes are actually saved and then handle the constraint violation if it happens. If you want to do it immediately your task becomes harder, which is the reason for this verbosity and general kludginess.
One more time - I'm recommending against the additional step of creating the read-only wrapper; I've put up some code anyway in case your spec requires it for some reason.
Is it getting hung up because OnaliasChanging is firing during initialization, so your backing field (alias) never gets initialized so it is always null?
Without more context, that's what it sounds like to me.
Our access client generates on the fly SQL inserts, update and delete instructions to be sent on a MS-SQL Server. Most users have the runtime version of Access 2007, and a few use the complete MS-Access version, 2003 or 2007. This morning one of our new users abroad, using a french/complete version of Access 2003, was unable to update data containing boolean fields.
It appeared that these fields are, in the french version of Access, populated with "Vrai/Faux" instead of "True/False" values. The problem was solved by installing the 2007 access runtime.
But I'd like to find a permanent solution, where I'd be able to read from somewhere which localized version of Access is in use and 'translate' the localized True/False values to standard True/False. I already checked the regional settings of the computer without success, so it is somewhere else. Any idea?
EDIT: Following JohnFX proposal, it is effectively possible to convert from local True/False to universal True/False with this simple function:
Function xBoolean(xLocalBooleanValue) as Boolean
if cint(xLocalBooleanValue) = -1 Then
xBoolean = True
endif
if cint(xLocalBooleanValue) = 0 Then
xBoolean = False
endif
end function
EDIT: following #David's comments, I changed the favorite solution. His proposal is smarter than mine.
EDIT: I am getting the Vrai/Faux values by reading the value of a field in a recordset:
? debug.print screen.activeForm.recordset.fields(myBooleanField).value
Vrai
True is NOT FALSE, or NOT 0, in all cases, no matter the localization or the database format.
So, if you replace all tests for True with NOT 0 and all tests for False with =0, then you've avoided the issue of localization of the Access keywords (I'm surprised that VBA and the Jet and Access expression services would not still understand True/False, though), as well as whichever convention your database engine uses for storing Boolean values.
In general, your data access layer ought to be abstracting that away for you. Both ODBC and ADO do it automatically, so you work with the Boolean values you know and it's taken care of for you transparently, in my experience.
I'm also still puzzled about the question, as it sounds like a display/formatting issue, but use NOT 0 and =0 for True and False avoids the problem entirely in all cases.
EDIT: In regard to the function edited into Philippe's question:
Is there a reason you've implicitly defined your function's parameter as a variant? Is that what you mean? If it's passed a Null, it's going error out on the first CInt(), as CInt() can't accept a Null.
Also, there's a logic problem in that in VBA any number but 0 is supposed to return True. It's also completely redundant code. This is simpler and returns the correct result in all cases:
Function xBoolean(xLocalBooleanValue As Vriant) as Boolean
If CInt(xLocalBooleanValue) <> 0 Then
xBoolean = True
End If
End Function
Or, pithier still:
Function xBoolean(xLocalBooleanValue As Variant) as Boolean
xBoolean = (CInt(xLocalBooleanValue) <> 0)
End Function
And to handle Nulls passed in the parameter:
Function xBoolean(xLocalBooleanValue As Variant) as Boolean
xBoolean = (CInt(Nz(xLocalBooleanValue, 0)) <> 0)
End Function
I'm not sure that's necessary in the context you're currently using it, but I always hate writing code where I can imagine a case where it will error out -- even if I know it can't break in its present context, you never know where it might end up getting used, so should you anticipate a condition that can be handled, you should handle it.
Premature optimization?
No -- it's putting a safety lock on a weapon that keeps it from being misused.
(on the other hand, if it took more lines of code to handle the antipated error than the function started out with, I'd think twice about it)
Have you considered using -1/0 (Access is weird about booleans) instead of true/false in your update and delete queries?
Math is the universal language, yaknow.
Also, to avoid having to localize the UI so much, why not use check-boxes instead of a text field for booleans on your UI?
Simple:
Function xBoolean(bool As Variant) As Boolean
xBoolean = Abs(Nz(bool, 0))
End Function
I am a bit of a newbie when it comes to Linq to SQL but I hope you can help out. I've written the following Linq to SQL statement with Extension Methods:
Cedb.ClassEvents.Where(c => c.ClassID == 1).Select(c => c).Single()
Where Cedb is the Datacontext, ClassEvents is a table (for classes and events being held at a facility) and ClassID is a unique integer key.
This query runs fine in LinqPad (without Cedb). When it returns, it says that the return type is "ClassEvent". In Intellisense in Visual studio, it tells me that the return type of this query is ClassEvent (created in my data model). However, when I try to place the results in a variable:
var classEvent = Cedc.ClassEvents.Where(c.ClassID == 1).Select(c => c).Single();
then I get an error: InvalidCastException: Specified cast is not valid. The same thing happens if I use the "ClassEvent" class in place of the var. I'm new to this but this one seems like a true slam dunk rather than a bug. Is there something about the Single method that I don't know that is leading to the error? Any help would be appreciated!
Slace - and any other interested parties. The cause of the "Invalid Cast Exception" error was a change in the underlying data model. A smallint field had been changed to bit. Thus, when the system tried to map the query results onto the "ClassEvent" data structure, the conflict between the model (which had not been updated) and the data table emerged.
Nonetheless, I do appreciate the answer!
You don't need to do both a Select and a Single, in fact, you don't even need the Where, you can get away with (see http://msdn.microsoft.com/en-us/library/bb535118.aspx):
var classEvent = Cedc.ClassEvents.Single(c => c.ClassID == 1);
I'd also recommend against using Single unless you're 100% sure that the Func<T, bool> will always return a value, as if it doesn't return a value you will have an exception thrown. Better is using SingleOrDefault and doing a null check before interaction with the object (http://msdn.microsoft.com/en-us/library/bb549274.aspx)
I've been using Linq to SQL for some time now and I find it to be really helpful and easy to use. With other ORM tools I've used in the past, the entity object filled from the database normally has a property indicating the length of the underlying data column in the database. This is helpful in databinding situations where you can set the MaxLength property on a textbox, for example, to limit the length of input entered by the user.
I cannot find a way using Linq to SQL to obtain the length of an underlying data column. Does anyone know of a way to do this? Help please.
Using the LINQ ColumnAttribute to Get Field Lengths from your Database :
http://www.codeproject.com/KB/cs/LinqColumnAttributeTricks.aspx
Thanks. Actually both of these answers seem to work. Unfortunately, they seem to look at the Linq attributes generated when the code-generation was done. Although that would seem to be the right thing to do, in my situation we sell software products and occasionally the customer will expand some columns lengths to accommodate their data. Thus, the length of the field as reported using this technique may not always reflect the true length of the underlying data column. Ah well, not Linq to SQL's fault, is it? :)
Thanks for the quick answers!
If you need to know the exact column length you can resort to the System.Data classes themselves. Something a bit like this:
var context = new DataContextFromSomewhere();
var connection = context.Connection;
var command = connection.CreateCommand( "SELECT TOP 1 * FROM TableImInterestedIn" );
var reader = command.ExecuteReader();
var table = reader.GetSchemaTable();
foreach( var column in table.Columns )
{
Console.WriteLine( "Length: {0}", column.MaxLength );
}