Entity Framework에 개체가 있는지 확인하는 가장 좋은 방법은 무엇입니까?


114

성능 관점에서 데이터베이스에 개체가 있는지 확인하는 가장 좋은 방법은 무엇입니까? Entity Framework 1.0 (ASP.NET 3.5 SP1)을 사용하고 있습니다.

답변:


228

SQL을 직접 실행하지 않으려면 가장 좋은 방법은 Any () 를 사용하는 것입니다 . Any ()가 일치하는 항목을 찾으면 바로 반환하기 때문입니다. 또 다른 옵션은 Count () 이지만 반환하기 전에 모든 행을 확인해야 할 수도 있습니다.

다음은 사용 방법의 예입니다.

if (context.MyEntity.Any(o => o.Id == idToMatch))
{
    // Match!
}

그리고 vb.net에서

If context.MyEntity.Any(function(o) o.Id = idToMatch) Then
    ' Match!
End If

그리고 VB에서 If (context.MyEntity.Any (o => o.Id <> idToMAtch)) Then '이것은 일치합니다! End If 죄송합니다. 이것은 코드 태그에 없습니다. 어떻게해야하는지 알 수 없습니다!
Kevin Morrissey

o.Id <> idToMatch가 일치와 같지 않음을 의미한다고 생각하십시오
Colin

이름으로 검색 할 때 ID가 있으면 어떻게하나요?
Mihai Bratulescu 2014 년

안녕하세요. 그것이 존재하는지 어떻게 확인하고 그 후에 모든 데이터를 선택할 수 있습니까?
virtouso 2015-04-07

1
@barnes T인 인터페이스로 제한 하고 IEnumerable를 포함하는 객체를 반환 Id하는 경우 일반 함수를 사용할 수 있어야합니다 IsExists<T>().
Suncat2000


5

새 데이터 레코드에서 제공되는 중복의 비율이 매우 높고 중복을 확인하기 위해 수천 건의 데이터베이스 호출이 발생하는 시나리오를 관리해야했습니다 (따라서 CPU는 100 %로 많은 시간을 보냈습니다). 결국 나는 마지막 100,000 개의 레코드를 메모리에 캐시하기로 결정했습니다. 이렇게하면 SQL 데이터베이스에 대한 LINQ 쿼리와 비교할 때 매우 빠른 캐시 된 레코드에 대한 중복을 확인한 다음 데이터베이스에 새 레코드를 기록 할 수 있습니다 (데이터 캐시에 추가 할 수도 있습니다. 길이를 관리 할 수 ​​있도록 정렬 및 트리밍).

원시 데이터는 구문 분석해야하는 많은 개별 레코드가 포함 된 CSV 파일이었습니다. 연속 된 각 파일의 레코드 (5 분마다 약 1 개의 비율로 발생)가 상당히 겹쳤으므로 중복 비율이 높습니다.

간단히 말해서, 타임 스탬프가있는 원시 데이터가 거의 순서대로 들어오는 경우 메모리 캐시를 사용하면 레코드 중복 검사에 도움이 될 수 있습니다.


2
우리 개발자가 시나리오를 생각해내는 경우가 많을 때 약간의 왜곡이있을 수 있습니다. 귀하의 솔루션을 C #으로 번역하여 우리와 향후 많은 개발자가 혜택을받을 수 있도록 요청하고 싶습니다. +1. 블로그 게시물까지 확장 된 솔루션을 좋아합니다! :)
sangam

3

나는 이것이 매우 오래된 스레드라는 것을 알고 있지만 나 같은 사람 이이 솔루션이 필요한 경우를 대비하여 VB.NET에서 위의 답변을 기반으로 사용한 것입니다.

Private Function ValidateUniquePayroll(PropertyToCheck As String) As Boolean
    // Return true if Username is Unique
    Dim rtnValue = False
    Dim context = New CPMModel.CPMEntities
    If (context.Employees.Any()) Then ' Check if there are "any" records in the Employee table
        Dim employee = From c In context.Employees Select c.PayrollNumber ' Select just the PayrollNumber column to work with
        For Each item As Object In employee ' Loop through each employee in the Employees entity
            If (item = PropertyToCheck) Then ' Check if PayrollNumber in current row matches PropertyToCheck
                // Found a match, throw exception and return False
                rtnValue = False
                Exit For
            Else
                // No matches, return True (Unique)
                rtnValue = True
            End If
        Next
    Else
        // The is currently no employees in the person entity so return True (Unqiue)
        rtnValue = True
    End If
    Return rtnValue
End Function

VB에서 Lambda를 사용하는 방법을 모르지만 C #에서는 동일합니다. return! context.Employees.Any (c => c.PayrollNumber == PropertyToCheck). 이렇게하면 모든 결과가 반환 된 다음 메모리에서 반복되는 것을 방지 할 수 있습니다.
Colin

1
@Colin 이것은 위의 코드에서 메모리 문제를 간과 한 좋은 추가입니다. VB에서 코드는 context.Employees.Any (c => c.PayrollNumber <> PropertyToCheck)입니다. 이제 이것을 내 코드에 추가했습니다.
Kevin Morrissey 2013 년

케빈, 돌아가서 코드를 수정해야 할 것 같습니다. 귀하의 논리는 일치하는 급여 번호가 없을 때 true가 아니라 일치하지 않는 급여 번호가 있으면 반드시 true를 반환합니다.
Colin

@Colin 죄송합니다. 귀하의 예제에 VB 버전을 제공하고 있었지만 C #이 옳지 않으며 ==가 내 VB <>와 같지 않다고 생각했습니다.
Kevin Morrissey 2013 년

1
@KevinMorrissey Coling이 "문맥"앞에 "Not"을 넣어야한다고 말한 것 같습니다. 이후 (I 반복) 않음 "이 없음 context.Employees.Any (c => c.PayrollNumber = PropertyToCheck)를 호출하는" IS NOT 같은 "반환 context.Employees.Any (c <> = c.PayrollNumber PropertyToCheck)" . 내 요점이 보이니? "return Any <>"를 사용하면이 숫자와 일치하지 않는 항목을 찾으면 (일치하는 숫자가있는 경우에도) 무엇이든 true를 반환합니다. 대신 "Not [...]. Any ="를 사용하면 찾고있는 행을 찾을 수 없을 때만 True가 반환됩니다! 차이점이 보이십니까?
Erx_VB.NExT.Coder

2

나는 이것에 약간의 문제가 있었다-내 EntityKey는 세 가지 속성 (3 열이있는 PK)으로 구성되어 있으며 추악하기 때문에 각 열을 확인하고 싶지 않았습니다. 모든 엔터티에서 항상 작동하는 솔루션에 대해 생각했습니다.

이것에 대한 또 다른 이유는 매번 UpdateExceptions를 잡는 것을 좋아하지 않기 때문입니다.

키 속성의 값을 얻으려면 약간의 Reflection이 필요합니다.

코드는 다음과 같이 사용을 단순화하기 위해 확장으로 구현됩니다.

context.EntityExists<MyEntityType>(item);

보세요 :

public static bool EntityExists<T>(this ObjectContext context, T entity)
        where T : EntityObject
    {
        object value;
        var entityKeyValues = new List<KeyValuePair<string, object>>();
        var objectSet = context.CreateObjectSet<T>().EntitySet;
        foreach (var member in objectSet.ElementType.KeyMembers)
        {
            var info = entity.GetType().GetProperty(member.Name);
            var tempValue = info.GetValue(entity, null);
            var pair = new KeyValuePair<string, object>(member.Name, tempValue);
            entityKeyValues.Add(pair);
        }
        var key = new EntityKey(objectSet.EntityContainer.Name + "." + objectSet.Name, entityKeyValues);
        if (context.TryGetObjectByKey(key, out value))
        {
            return value != null;
        }
        return false;
    }

1
이제 거의 9 살이 된 내 답변에 의견을 추가하고 싶습니다. 요즘에는 Entity Framwork 4를 사용하는 2010/2011보다 훨씬 더 깨끗한 솔루션과 가능성이 있다고 생각합니다. 따라서이 답변에 대한 투표를 중지하는 대신 아래에 새롭거나 더 나은 답변을 추가하는 것이 좋습니다.
Sven

또한 내 솔루션은 변경할 수없는 기존 테이블 / 엔티티의 복합 키를 사용하여 많은 엔터티에서 작동하는 일반적인 솔루션이라는 점을 명심하십시오. 따라서 항상 3 개의 주요 속성으로 .Any (...)를 쿼리하는 대신 .EntityExists ()를 호출했습니다.
Sven

2

객체가 null인지 확인하기 만하면 100 % 작동합니다.

    try
    {
        var ID = Convert.ToInt32(Request.Params["ID"]);
        var Cert = (from cert in db.TblCompCertUploads where cert.CertID == ID select cert).FirstOrDefault();
        if (Cert != null)
        {
            db.TblCompCertUploads.DeleteObject(Cert);
            db.SaveChanges();
            ViewBag.Msg = "Deleted Successfully";
        }
        else
        {
            ViewBag.Msg = "Not Found !!";
        }                           
    }
    catch
    {
        ViewBag.Msg = "Something Went wrong";
    }

0

왜하지 않습니까?

var result= ctx.table.Where(x => x.UserName == "Value").FirstOrDefault();

if(result?.field == value)
{
  // Match!
}

결과를 찾을 수없는 경우 FirstOrDefault ()가 null을 반환하므로 null 참조 예외가 발생합니다. 나는 그것을 피하기 위해 if (result? .field == value) 할 수 있다고 생각합니다.
ToDevAndBeyond

엔터티를로드하기 때문에 불필요하게 느려질 수 있습니다. 원하는 것은 키가 있는지 확인하는 것뿐입니다.
Douglas Gaskell

0

그것을하는 가장 좋은 방법

객체가 무엇이고 데이터베이스의 테이블에 관계없이 필요한 것은 객체의 기본 키뿐입니다.

C # 코드

var dbValue = EntityObject.Entry(obj).GetDatabaseValues();
if (dbValue == null)
{
   Don't exist
}

VB.NET 코드

Dim dbValue = EntityObject.Entry(obj).GetDatabaseValues()
If dbValue Is Nothing Then
   Don't exist
End If

왜 두 개의 거의 동일한 답변입니까? 그 차이는 미미합니다. 또한 이것이 최선의 방법은 아닙니다. 레코드가 있는지 확인하기 위해서만 데이터베이스에서 모든 값을 가져 오는 것은 이치에 맞지 않습니다. 가 존재 .
Gert Arnold
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.