web-dev-qa-db-ja.com

Entity Frameworkにオブジェクトが存在するかどうかを確認する最良の方法は?

パフォーマンスの観点からデータベースにオブジェクトが存在するかどうかを確認する最良の方法は何ですか? Entity Framework 1.0(ASP.NET 3.5 SP1)を使用しています。

105
Freddy

SQLを直接実行したくない場合、最良の方法は Any() を使用することです。これは、Any()が一致を見つけるとすぐに戻るためです。もう1つのオプションは 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
210
Alex Angas

パフォーマンスの観点から、 EXISTS コマンドを使用した直接SQLクエリが適切だと思います。 Entity FrameworkでSQLを直接実行する方法については、こちらをご覧ください: http://blogs.Microsoft.co.il/blogs/gilf/archive/2009/11/25/execute-t-sql-statements-in- entity-framework-4.aspx

7
Konamiman

新しいデータレコードで提供される重複の割合が非常に高く、重複をチェックするために何千ものデータベース呼び出しが行われたシナリオを管理する必要がありました(したがって、CPUは100%で多くの時間を送信しました)。最後に、最後の100,000レコードをメモリにキャッシュしておくことにしました。このようにして、SQLデータベースに対するLINQクエリと比較して非常に高速であるキャッシュされたレコードに対する重複をチェックし、データベースに真に新しいレコードを書き込むことができます(データキャッシュに追加するだけでなく、その長さを管理しやすいようにソートおよびトリミングされます)。

生データは、解析する必要がある多くの個別のレコードを含むCSVファイルであったことに注意してください。連続する各ファイル(5分ごとに約1の割合で発生)のレコードはかなり重複していたため、重複の割合が高くなりました。

手短に言えば、生のデータにタイムスタンプが付いていて、ほとんど順番どおりに到着している場合、メモリキャッシュを使用すると、レコードの重複チェックに役立つ場合があります。

5
ProfNimrod

私はこれが非常に古いスレッドであることを知っていますが、私のような誰かがこのソリューションを必要とする場合に備えて、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
4
Kevin Morrissey

これにはいくつかの問題がありました-EntityKeyは3つのプロパティ(3列のPK)で構成されており、各列を確認するのは面倒だからです。すべてのエンティティで常に機能するソリューションを考えました。

このもう1つの理由は、毎回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;
    }
3
Sven

オブジェクトが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";
    }
2
user4584103

しませんか?

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

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