Вопрос по оптимизации запросов LINQ-TO-SQL - PullRequest
2 голосов
/ 20 июня 2011

У меня есть таблица соединений Person's Sports со следующей схемой:

PersonId
SportID

Как эффективно настроить спорт человека в одной транзакции, т.е.

void SetPersonsSports(List<PersonsSportsL> sports);

Мой способ сделать это - сначала удалить все виды спорта человека с помощью x.PersonId = PersonId, а затем снова добавить все виды спорта, но я знаю, что операция удаления стоит дорого, и я хотел посмотреть, что делают другие люди, сталкиваясь с подобной задачей. .

Спасибо.

UPDATE:

Вот о чем я думал ....

    void SetPersonsSports(List<PersonsSports> PersonSports) 
    {

        using (DataContext dc = conn.GetContext())
        {
            if (PersonSports.Select(x=>x.PersonID).Distinct().Count()>1)
                throw new Exception("This method can only be used with a set of sports for the same person ID at a time");
            var sportIDs = PersonSports.Select(x=>x.SportID);
            bool submitFlag = false;                
            var toRemove = dc.PersonSports.Where(x=>!sportIDs.Contains(x.SportID));
            if (toRemove.Count()>0)
            {
                 dc.PersonSports.DeleteAllOnSubmit(toRemove);
                 submitFlag = true;
            }
            var toAdd = dc.PersonSports.Where(x=>!sportIDs.Contains(x.SportID));
            if (toAdd.Count()>0)
            {
                 dc.PersonSports.InsertAllOnSubmit(toAdd);
                 submitFlag = true;
            }
            if (submitFlag)
                 dc.SubmitChanges();

        }
    }

1 Ответ

2 голосов
/ 20 июня 2011

Ваше предложение полностью верно - лучшего способа сделать это не существует.

У вас есть небольшая ошибка / опечатка

var toAdd = dc.PersonSports.Where(x=>!sportIDs.Contains(x.SportID)); 

, который должен быть (и вы должны использовать верблюжий случай для параметров метода)

var toAdd = PersonSports.Where(x=>!sportIDs.Contains(x.SportID)); 

Единственное, что я хотел бы сделать, это подумать о том, нужно ли вам определять, какие записи следует удалять и удалять, прежде чем выполнять какие-либо операции вставки и обновления базы данных. Вы можете столкнуться с проблемами, если ваш метод более сложный, чем этот, потому что коллекция может измениться до того, как вы перечислите. Я предпочитаю, чтобы мои коллекции оценивались немедленно.

// just get the sport ids from the database here 
// rather than the entire PersonSport objects
var toRemove = dc.PersonSports.Where(x=>!sportIDs.Contains(x.SportID)).ToList();
var toAdd = PersonSports.Where(x=>!sportIDs.Contains(x.SportID)).ToList(); 

if (toRemove.Any())
{
    dc.PersonSports.DeleteAllOnSubmit(toRemove);                        
}               

if (toAdd.Any())               
{                    
    dc.PersonSports.InsertAllOnSubmit(toAdd);
}

dc.SubmitChanges();

Наконец, обратите внимание, что это прекратится, если у вас более 2100 видов спорта, потому что идентификаторы будут отправлены в качестве параметров, а это жесткий предел SQL для максимального количества параметров. Если это проблема, вы можете подсчитать, сколько параметров вы работаете, и выполнить их 2000 одновременно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...