Я изо всех сил пытаюсь найти эффективный способ выполнения запроса по таблицам с использованием Entity Framework.
У меня есть две таблицы, одна из которых содержит объекты Foos , а другая - сравнения между этими объектами FooComparisons . Процесс сравнения между двумя Foos является сложным вычислением.
Запрос, который я хотел бы выполнить эффективно, заключается в следующем: для каждого Foo в базе данных, с которой не связано сравнение, запустите процесс сравнения с целом Foo с возможностью обработки данных, кроме меня и сохранения результатов в FooComparison таблице.
Как и ожидалось, таблица FooComparison становится огромной довольно быстро (для каждого new Foo -n, мы добавляем n-1 записей в таблицу), и способ, которым я первоначально выполнял эту операцию, не является устойчивым: я сохраняю все данные в памяти, чтобы иметь возможность выполнить запрос LINQ для IEnumerable .
Каков будет правильный способ выполнения этой операции с использованием Entity Framework? Я уверен, что объединение должно сделать трюк, но я не могу понять, как.
Спасибо за вашу помощь.
public class Foo
{
public int Id { get; set; }
public string Description { get; set; }
}
public class FooComparison
{
public int Id { get; set; }
public int Foo1Id { get; set; }
public int Foo2Id { get; set; }
public int SimilarityIndex { get; set; }
}
public class FooContext : DbContext
{
public DbSet<Foo> Foos { get; set; }
public DbSet<FooComparison> FooComparisons { get; set; }
}
public class ComparisonService
{
public async Task<int> RunComparisonUpdate(FooContext context)
{
var allFoos = context.Foos.ToArray();
var alreadyRun = context.FooComparisons.Select(x => new {x.Foo1Id, x.Foo2Id}).Distinct().ToArray();
//we store all data in memory, I cannot perform the LINQ Query below otherwise, I know this is not right way of doing it!
var toRun = allFoos
.Where(x => alreadyRun.All(y => y.Foo1Id != x.Id && y.Foo2Id != x.Id)).ToArray(); //complex query that I cannot run directly against the context
foreach (Foo foo in toRun)
{
foreach (Foo other in allFoos)
{
if (other.Equals(foo)) continue;
context.FooComparisons.Add(Compare(foo, other));
}
}
return await context.SaveChangesAsync();
}
private FooComparison Compare(Foo foo1, Foo foo2)
{
//lengthy calculation
return new FooComparison()
{
Foo1Id = foo1.Id,
Foo2Id = foo2.Id,
SimilarityIndex = 42 //result of the calculation
};
}
РЕДАКТИРОВАТЬ
I Мы нашли гораздо лучший способ сделать это в этом посте. Но после его реализации я получаю время ожидания запроса один раз каждые два запроса. Я мог бы увеличить тайм-аут, но это не кажется устойчивым решением (я думаю, тайм-аут случится снова, когда база данных увеличится).
Есть ли другое решение?
public async Task<int> RunComparisonUpdate_MuchBetter(FooContext context)
{
var Id1s = context.FooComparisons.Select(x => x.Foo1Id);
var Id2s = context.FooComparisons.Select(x => x.Foo2Id);
var toRun = context.Foos.Where(x => !Id1s.Contains(x.Id) && !Id2s.Contains(x.Id)).ToArray();
foreach (Foo foo in toRun) {
foreach (Foo other in context.Foos) {
if (other.Equals(foo)) continue;
context.FooComparisons.Add(Compare(foo, other));
}
}
return await context.SaveChangesAsync();
}