Entity Framework запрос по базам данных - PullRequest
0 голосов
/ 17 марта 2020

Я изо всех сил пытаюсь найти эффективный способ выполнения запроса по таблицам с использованием 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();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...