Linq to SQL - Underlying Column Length - linq-to-sql

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 );
}

Related

Contao CMS Query a 'checkboxWizard' BLOB field

I have a question about how to query a 'checkboxWizard' BLOB field. In have added a such field to tl_member. This is working very fine. I can add “0 to N” selection to each members. Let’s call this field “myBlob”.
Now the questions is how to query “myBlob” with the Contao way? Let’s say I want all member that are in the postal code “12120” and that have the id “2” of “myBlob” selected. Not only “2” but at least this one.
$arrColumn[] = "tl_member.postal=?";
$arrValues[] = 12120;
$arrColumn[] = "tl_member.myBlob=?"; <- how to say “contains in the blob” here?
$arrValues[] = 2;
self::findBy($arrColumn, $arrValues)
The only way to do this (when using the default Contao method for such relationships) is to create a query like:
… WHERE myBlob LIKE '%"2"%'
So in your case it might be:
$arrColumn[] = "tl_member.myBlob LIKE ?";
$arrValues[] = '%"2"%';
However, this is of course cumbersome and might not work in all cases.
May be a better way would be to use codefog/contao-haste with its 'many to many' helper: https://github.com/codefog/contao-haste/blob/master/docs/Model/index.md
This way you will have a separate table containing the references.

How do I convert mysql spatial POINT into a readable format in a yii model?

I have a yii model that is based on a mysql table with a spatial POINT field. When viewing a record of this model I want to display the coordinates in the format of "55.0000, -89.5000".
In the default generated CRUD view, currently it displays nothing for this field.
I'm thinking I have to use the mysql AsText function somehow, perhaps in beforeFind()?
How can I do this?
UPDATE
I found I can get the value to print as "POINT(55.0000, -89.5000)" using the following:
public function beforeFind()
{
parent::beforeFind();
$criteria = new CDbCriteria();
$criteria->select = "AsText(coordinates) AS coordinates";
$this->dbCriteria->mergeWith($criteria);
}
However, this has the unfortunate side effect of causing all the other fields to be "Not Set".
I guess the default value for $criteria->select is "*". By setting $criteria->select = "AsText(coordinates) AS coordinates" I was over writing the * and thus only returning the single column. So what I did was change the line to manually specify the other columns in addition to the coordinates column:
$criteria->select = "id,name,street,city,AsText(coordinates) AS coordinates";
Not sure if this is the ideal way but it's working for me. I believe this would be the same thing you'd have to do to use other database functions in the select.

Linq-to-SQL EntitySet Is Not IQueryable -- Any Workarounds?

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.

Losing DateTimeOffset precision when using C#

I have a SQL Server table with a CreatedDate field of type DateTimeOffset(2).
A sample value which is in the table is 2010-03-01 15:18:58.57 -05:00
As an example, from within C# I retrieve this value like so:
var cmd = new SqlCommand("SELECT CreatedDate FROM Entities WHERE EntityID = 2", cn);
var da = new SqlDataAdapter(cmd);
DataTable dt =new DataTable();
da.Fill(dt);
And I look at the value:
MessageBox.Show(dt.Rows[0][0].ToString());
The result is 2010-03-01 15:18:58 -05:00, which is missing the .57 that is stored in the database.
If I look at dt.Rows[0][0] in the Watch window, I also do not see the .57, so it appears it has been truncated.
Can someone shed some light on this? I need to use the date to match up with other records in the database and the .57 is needed.
Thanks!
Darvis
SQL Server doesn't have millisecond precision.
Here's an article that goes into the details:
Advanced SQL Server DATE and DATETIME Handling
EDIT
I'm guessing C# shouldn't show the same behavior. Keep in mind that the DateTime.ToString() method doesn't include milliseconds unless you specify a Format Provider.
The Watch window would also be showing you ToString(). Try setting a Breakpoint and use the Inspector to get the more detailed information being stored and see if you mililseconds are there.
Fill should change the data in the dataset to match the data in the datasource -- have you tried any other methods to retrieve the data to see if other classes retrieve the data in the format you are hoping for? Simple tests like sqldatasource/gridview, etc

Why am I getting "Invalid Cast" when using Linq to SQL?

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)