views:

230

answers:

3

I have a LINQ entity that I need to create a special string value for. It is 7 different values separated by "-". Some of the fields used are in that table, while some of them are in different tables. I would like to add this field to the entity somehow so that I don't have to create this string myself every time I need it.

I was thinking I could add it to the entity with a partial class like this:

    public string SpecialField
    {
        get
        {
            return string.Format("{0}-{1}-{2}-{3}-{4}-{5}-{6}",
                                 TableId,
                                 Number,
                                 ForeignTableA.Date,
                                 ForeignTableB.Name,
                                 ForeignTableC.ForeignTableD.Name,
                                 ForeignTableB.ForeignTableE.Name,
                                 ForeignTableB.Number ?? 0);
        }
    }

However, after writing that, I became a bit unsure how that would work. Cause, unless I am mistaken, this would result in a database query every time that value is used for every item. And would it work to for example use that field in a Where clause?

I need to use that field in a Where clause, and I would like it to happen at the server so I don't fetch more data than I need to.

How would you best do this?

+1  A: 

I think you'll need a let clause with a dash of anonymous types. I haven't tested this, but something like this might do the trick:

var query = from master in MasterTable
            join foreignA in ForeignTableA on ...
            join foreignB in ForeignTableB on ...
            let special = string.Format ("...", master.TableID, ...)
            where special.Contains ("foo")
            select { 
                 // ...
                 string specialResult = special,
                 // ...
            }
XXXXX
but this is done in the query itself, which means I would have to add that `let special = string.Format( ...` to every query that needs it. Which would be kind of annoying, especially if it needed to change.
Svish
You can put the actual format in a method: let special = ComputeSpecial (master, foreignA, foreignB). If you're storing references to foreign objects in your master object, you can always use those. But you need to get the actual contents of the foreign rows one way or another.If you want to have the server do everything, AFAIK you'll need a stored procedure; I'm not at all expert on stored procedures, though.
XXXXX
@Larry: I'm not sure, but I think calling your own methods is not supported...
ShdNx
You can most definitely call *some* functions in a LINQ query; I'm not sure what restrictions may exist. I'm using them often, and I haven't stumbled on any counterintuitive problems.
XXXXX
+2  A: 

You could create a view in the database to this for you. This way SQL Server takes care of it and you can query on it more efficiently

Jonathan van de Veen
Can you have foreign keys in views, so I could get a 1-to-1 relationship in my linq entities or something?
Svish
Not sure if I understand your question completely. Yes, you can include foreign key columns in your views, so you can relate to other data, however the relations are always enforced on the table and not on the view.If you want to do some sort of lookup from the rest of the data, that will work, but it would still not perform at it's best. I would put all the data I would need for this request in that view if possible and query the view only.
Jonathan van de Veen
A: 

How about caching the value after you've read it once? It won't be ultra-efficient like it would be if you got all of these values at once, but it would prevent multiple attempts to get the same value. (Of course, this only works if the SpecialField content doesn't change while in use.)

protected string specialField = null;

public string SpecialField
{
    get
    {
        if (specialField == null)
        {
            specialField = string.Format("{0}-{1}-{2}-{3}-{4}-{5}-{6}",
                             TableId,
                             Number,
                             ForeignTableA.Date,
                             ForeignTableB.Name,
                             ForeignTableC.ForeignTableD.Name,
                             ForeignTableB.ForeignTableE.Name,
                             ForeignTableB.Number ?? 0);
        }
        return specialField;
    }
}
John Fisher