简体   繁体   中英

C# EF best way to lookup data from one table within another

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

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/

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 ).

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM