views:

47

answers:

3

I have a table in SQL Server 2008 with uniqueidentifier field.

In my application (C#, WPF) I have a textbox which intended for search some data by GUID, user can enter guid by typing, ctrl+v, etc, so he/she can make an error.

What is the best and fastest approach to make a search by this field using linq2sql ignoring whitespaces, "-"... any other characters?

var d = from status in dc.FolderStatus.Where(status => status.Date <= DateTime.Now 
                    && status.Folder.TapeCode.ToString().Replace("-", "") == tapeCode.ToUpper().Replace("-", "").Replace(" ", "")
                    )

TapeCode is uniqueidentifier in SQL Server 2008 and Guid in dbml file. Is it ok?

+3  A: 

No, that will be extremely slow (it'll have to do a table scan, convert each identifier to a string and compare the string). Instead, you'll have to convert the input string to a Guid and compare that:

tapeCode = Regex.Replace(tapeCode, "[^0-9a-zA-Z]+", "");
Guid id = Guid.Parse(tapeCode);
var d = from status in dc.FolderStatus
        where status.Date <= DateTime.Now 
           && status.Folder.TapeCode == id
        select status;

(Note that Guid.Parse method accepts 32 hexadecimal digits without dashes as a valid input).

Dean Harding
(Note that Guid.Parse was introduced in .NET 4. Prior to that you had to call the constructor.)
Jon Skeet
@Jon: Oooooh, so that's why I couldn't find it in Reflector (to see whether it supported 32 hex digit format), I thought I was going mad :)
Dean Harding
A: 

If it's a uniqueidentifier field in SQL, I'd expect native support in LINQ to SQL. I believe you should be able to do:

Guid tapeCode = new Guid(text);
var d = from status in dc.FolderStatus
        where status.Date <= DateTime.Now && status.Folder.TapeCode == tapeCode
        select ...;

Now of course that will throw an exception if text doesn't represent a valid GUID. If you're using .NET 4, you can use Guid.TryParse in the same way you would for parsing integers etc:

Guid tapeCode;
if (Guid.TryParse(text, out tapeCode))
{
    var d = from status in dc.FolderStatus
            where status.Date <= DateTime.Now &&
                  status.Folder.TapeCode == tapeCode
            select ...;
}
else
{
    // Handle invalid input
}
Jon Skeet
A: 

You shouldn't try and do .Replace on the SQL field, as this will actually get executed on the server, which is very slow.

You should massage the data coming in to your method.

I.e

public void GetFoo(string guid)
{
     string sqlGuid = guid.ToString().Trim().Replace("-", "");

     var d = from status in dc.FolderStatus.Where(status => status.Date <= DateTime.Now &&
                                                            status.Folder.TapeCode == sqlGuid);
}
RPM1984