3

I met situation I have to write app where I'm taking bunch of records from tableA then for each of record I have to do lookup against tableB to pull extra information (get another 3 columns).

TableA is a small table (<1000 records), but tableB is much bigger. Also, these resides in separate DB on the same DB server.

What would be best approach to get it optimized?

There is no option to get all records into list of objects from tableB then operate on it, rather I would need to run LINQ query for each of tableA element(object) against tableB. This is part of my MVC so could you please provide me an draft of solution, described at high level, rather than providing code.

EDIT The tableA records need to be "enriched" all against tableB before they are displayed, in effecitve this may be +/- 500 tableA records to be lookup against tableB. Also, limitation is I have only read access to the tableB..no option to write procedures, etc

smirQ
  • 51
  • 3
  • I've forgotten to mention, the tableA records need to be "enriched" all against tableB before they are displayed, in effecitve this may be +/- 500 tableA records to be lookup against tableB – smirQ Apr 09 '17 at 21:22

3 Answers3

0

You could create a view in one of the databases that combines data in table A and B. Then map your entity to that view. Check this out https://www.mssqltips.com/sqlservertip/1990/how-to-use-sql-server-views-with-the-entity-framework/

Jrnek
  • 1
  • Sorry mate, haven't told this but I have only read acces to the DBs. One p[lace I can manipulate is the my app side. – smirQ Apr 09 '17 at 21:26
0

Without seeing your models and query, it is hard to provide an accurate answer. However, the best start is within the database (I would assume SQL Server 2012+).

From your description, the generated query should look, in a very simplified way, like the following:

SELECT A.*, B.Col1, B.Col2, B.Col3
FROM Db1.dbo.TableA AS A
   JOIN Db2.dbo.TableB AS B ON B.Id = A.FkToBId

According to this question and its accepted answer, there is no big difference between selecting from the same database vs. selecting from another database within the same instance.

If TableB is big, you should avoid table scans, so the following index should be a good start:

CREATE INDEX IDX_TableB_Id ON TableB (Id) INCLUDE (Col1, Col2, Col3)

However, if the schema is properly normalized, the lookup key should also be a primary key and this index should not be required. I think that if it is clustered, it might bring extra benefit.

Of course, there is a chance that your LINQ generates a slightly different query. If this is the case, edit your question and include table schema, LINQ and generated query.

[EDIT]

Using SqlQuery is an option, but I am thinking about another way:

1) Generate a database context for each database. Lets call them DbContextA and DbContextB

2) Get only required information from TableB, store it in a dictionary for fast lookups and use in an aggregated query.

var ids = DbContextA.TableA.AsNoTracking().Select(item => item.FkToBId).ToList();
var bInfo = DbContextB.TableB.AsNoTracking()
   .Where(item => ids.Contains(item.id)) 
   .ToDictionary(
         item => item.Id, 
         item => new { item.Col1, item.Col2, item.Col3 }
   );

var aggrInfo = DbContextA.TableA.AsNoTracking()
   .ToList()
   .Select(item => new 
       { 
            AField = item, 
            Col1 = bInfo[item.FkToBId],
            Col2 = bInfo[item.FkToBId],
            Col3 = bInfo[item.FkToBId]
       };

If this does not provide the required efficiently, SqlQuery remains the only option, as a database context cannot work with two databases at once (source).

Community
  • 1
  • 1
Alexei - check Codidact
  • 20,117
  • 15
  • 137
  • 145
  • That would work If I could make a one LINQ query to both Entities(DBs) with Join ..but Im not sure this can be an option here, just has litle of experience so far.. – smirQ Apr 09 '17 at 21:29
  • You can use `DbContext.Database.SqlQuery()` extension method. You pass in the custom SQL query as mentioned in this anwser and set the type parameter `T` as a type with the same properties as the output of the query. [example](https://msdn.microsoft.com/en-us/library/jj592907(v=vs.113).aspx) – erikbozic Apr 09 '17 at 22:38
  • Got it working using join. One slight change I had to do is to ensure both tables are under same DB Context. – smirQ Apr 12 '17 at 09:53
0

You should create a one class means .cs file and add all the columns of TableA and TableB which is required.

Let see and Example Here i am having two tables category and sub category i want the name of the category and want to show the list.

public class SubCategory
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Image { get; set; }
    public Nullable<bool> Isdisplay_ { get; set; }
    public Nullable<int> CatId { get; set; }
    public string CatName { get; set; }

}

var data = (from t in db.SubCategories
join ts in db.Categories on t.CatId equals ts.CategoryId 
select new { a1 = t.SubId, a2 = t.SubImage, a3 = t.SubIsdisplay_, a4 = 
 t.SubName, a5 = ts.CategoryName }).ToList();

        List<SubCategory> p1 = new List<SubCategory();
        foreach (var i in data)
        {
            SubCategory p2 = new SubCategory();
            p2.Id = i.a1;
            p2.Name = i.a4;
            p2.Image = i.a2;
            p2.Isdisplay_ = i.a3;
            p2.CatName = i.a5;

            p1.Add(p2);
        }
        return p1;

Now you can use the list p1 to show your data.

Community
  • 1
  • 1
Arpit Shah
  • 37
  • 1
  • 9