2012-02-15 7 views
9

Я использую Ado.net Entity Framework в первый раз, и мне нужно проверить, существует ли эта запись, прежде чем вставлять ее в базу данных. Я предпочитаю искать, если AuthodSSID существует, а не ключ (AuthorID). Я использую VS2010, Framework 4. System.Data.Entity - 3.5.0.0.Проверьте наличие записи перед вставкой новой записи

Я googled, но не нашел ответа на этот вопрос.

PublishingCompanyEntities publishContext; 
publishContext = new PublishingCompanyEntities(); 

private void createNew_Click(object sender, EventArgs e) 
{ 
    Author newAuthor = new Author(); 
    newAuthor.FirstName = firstName.Text; 
    newAuthor.LastName = lastName.Text; 
    newAuthor.AuthodSSID = 20; 
    newAuthor.AuthorID = 10 
//Check if record exist here 
    publishContext.AddToAuthor(newAuthor);//insert if does not exist 

} 
+1

Старый, но по-прежнему выглядит как DUP; более подробную информацию можно найти по адресу http://stackoverflow.com/questions/1802286/best-way-to-check-if-object-exists-in-entity-framework – Nenotlep

+0

Возможный дубликат [Лучший способ проверить, существует ли объект в Entity Framework?] (Https://stackoverflow.com/questions/1802286/best-way-to-check-if-object-exists-in-entity-framework) –

ответ

14

Единственный способ проверить, если запись существует, является запрос записи и посмотреть, если что-нибудь возвращается:

var existingAuthorCount = publishContext.Author.Count(a => a.AuthodSSID == 20); 
if (existingAuthorCount == 0) 
{ 
    // Do your insert 
} 
+1

Работая, нужно было выяснить, почему не появился .Count. Простой, с использованием System.Linq; не хватало на вершине! Tkx !! – BirdOfPrey

+0

Из мудрого совета печально известного Эрика Липперта: у вас есть кувшин, полный копейки. Кто-то спрашивает вас: «Есть ли в этом банке какие-то гроши?». ** Вы считаете их, а затем сравниваете ответ с нолем или видите ли в банке хотя бы одну копейку? ** ([Citation] (http://stackoverflow.com/questions/9194908/safely- проверка-не-воспроизводимый-ienumerables-для-пустота # comment11574518_9194908)). Производительность этого решения будет зависеть от количества строк, содержащихся в 'Author'. Я обновил свой ответ, чтобы ограничить получаемый запрос только поиском 1. –

+4

Можете ли вы не использовать publishContext.Author.Any (a => a.AuthodSSID == 20) или есть .Any() недоступно в EF? –

12

Что-то, как это должно работать:

if (publishContext.Author.Select(a => a.AuthodSSID).Where(id => id == 20).Take(1) == null) 
    // It doesn't exist 
else 
    // It does exist 

Основываясь на моем (хотя и фундаментальной) понимание этого следует произвести SQL заявление, эквивалентную:

SELECT TOP(1) AutodSSID FROM Author WHERE AuthodSSID = 20; 

Другой простой подход может заключаться в использовании метода расширения Any:

if (!publishContext.Author.Any(a => a.AuthodSSID == 20)) 
    // Put your insert logic here. 
+0

Это будет работать, и лучше всего, если вы хотите обновить автор, если он существует. Тем не менее, это выберет все столбцы для автора, которые вам могут не понадобиться.Выполнение счета, как в моем ответе, было бы более эффективным. – Jacob

+0

@Jacob - Счет будет фактически таким же, как включение одного столбца, но с использованием 'SingleOrDefault' я бы подумал, что он будет делать« TOP 1 », где' COUNT (*) 'все еще нуждается в * все * записи, или я чего-то не хватает? –

+1

Хороший вопрос. Моя проблема с «ТОП-1» заключается в том, что все * столбцы * все еще возвращаются для одной строки. 'COUNT' может потребовать больше сканирования таблицы в базе данных, но будет возвращено только целое число. Возможно, лучший выбор - сделать «Где», затем «Выбрать» первичного ключа, а затем «Take (1)». Это должно решить обе проблемы. – Jacob

0

Все, что вам нужно сделать, это поиск (с linq) для автора с этим идентификатором.

Метод Where() возвращает коллекцию авторов, в которой вы нуждаетесь только в этом, поэтому вы используете FirstOrDefault(), который возвращает первый элемент или null, если ничего не существует. Вы также можете использовать SinglOrDefault, который генерирует исключение, если в списке больше одного элемента или просто возвращает этот элемент.

Кажется, что @Jacob имеет отличный, более эффективный подход!

var author = publishContext.Authors.Where 
           (a=>a.AuthodSSID == 10).FirstOrDefault(); 
if(author == null) //none exist 
{//don't bother creating one unless you need to.. 
    Author newAuthor = new Author(); 
    newAuthor.FirstName = firstName.Text; 
    newAuthor.LastName = lastName.Text; 
    newAuthor.AuthodSSID = 20; 
    newAuthor.AuthorID = 10 
    publishContext.AddToAuthor(newAuthor);//insert if does not exist 
} 
2

Я лично предпочитаю этот подход с точки .NET зрения. Это чище, и если вы заботитесь о скорости (в .NET), она более эффективна, однако SQL не является такой вспышкой;

private bool CheckIfEntityRecordExists(Entity e) 
{ 
    var retVal = false; 
    using (var db = new EntityContext()) 
    { 
     retVal = db.AdviserClients.Any(a => a.Id == e.Id); 
    } 
    return retVal; 
} 

Таким образом, для эффективного заявления SQL, следующее самое лучшее:

private bool CheckIfEntityRecordExists(Entity e) 
{ 
    var retVal = false; 
    using (var db = new EntityContext()) 
    { 
     retVal = db.AdviserClients.Count(a => a.Id == e.Id) > 0; 
    } 
    return retVal; 
} 
+1

, хотя у меня был ответ на ваш ответ, но с точки зрения производительности следует использовать db.context.Any(), поскольку db.contex.count() будет перебирать все данные while. Любой остановится только в 1-м матче. –

0

Там так называемый "upsert" операция доступна в EF v5.0 +

publishContext.Author.AddOrUpdate(x => x.Id, newAuthor) 

AddOrUpdate можно найти в пространстве имен System.Data.Entity.Migrations, поэтому не забудьте добавить:

using System.Data.Entity.Migrations; 

Операция AddOrUpdate не является атомарной. Но * if (existingAuthorCount == 0) {// Делаем вашу вставку} тоже.

Смежные вопросы