Entity Frameworkから単一のレコードを削除しますか?


195

Entity FrameworkにSQL Serverテーブルがあり、という名前employの単一のキー列が付いていIDます。

Entity Frameworkを使用してテーブルから単一のレコードを削除するにはどうすればよいですか?


2
db.employ.Remove(db.employ.Find(ID1))
Carter Medlin

2
@CarterMedlin-これは機能しますが、2つのデータベースヒットがあります。1つはSELECTで、もう1つはDELETEです。ほとんどの人は、特にselectがおそらく削除よりもかなり長い時間を要するので、それが非常に無駄であることに気付きます。
Davor 2017

パフォーマンスの問題のため、エンティティフレームワークのRemoveまたはRemoveRangeの使用はお勧めしません。私はむしろ次のように非常に単純なものを使用したいだけです。this.your_context.Database.ExecuteSqlCommand(sql、new SqlParameter( "@ your_parameter"、yourParameter));
curiousBoy 2018

2
@curiousBoy私が提案したようなステートメントを実行すると、EF6キャッシュは変更を反映しないと思います。
Yitzchak

回答:


362

最初にオブジェクトをクエリする必要はありません。IDによってオブジェクトをコンテキストにアタッチできます。このような:

var employer = new Employ { Id = 1 };
ctx.Employ.Attach(employer);
ctx.Employ.Remove(employer);
ctx.SaveChanges();

または、添付されたエントリの状態を削除済みに設定できます。

var employer = new Employ { Id = 1 };
ctx.Entry(employer).State = EntityState.Deleted;
ctx.SaveChanges();

87
または、ctx.Entry(employer).State = EntityState.Deleted
Simon Belanger 2013

12
これは、関係がカスケード削除として定義されている場合にのみ機能します。そうでない場合、上記のコードはFK例外で失敗します。
baruchl 2014

6
@mt_serg、私は3ステップ先を見ています。このような単純なレコードをDBから本当に削除する必要があったのは、いつ最後ですか。通常、FK関係を含むより複雑なレコードを処理します。したがって、私のコメント。
baruchl 2014

2
@IanWarburton 2行目と3行目(接続と削除)
Simon Belanger

4
@PaulZahra:他のクエリまたはソースからのIDのリストがあり、それを削除する必要がある場合があります。削除するためだけにオブジェクトをロードするのではなく、IDを使用して削除できます。SQLでDELETEステートメントが正常に機能するのはこの方法です。
シリド

82

を使用SingleOrDefaultして、条件に一致する単一のオブジェクトを取得し、それをRemoveEFテーブルのメソッドに渡すことができます。

var itemToRemove = Context.Employ.SingleOrDefault(x => x.id == 1); //returns a single item.

if (itemToRemove != null) {
    Context.Employ.Remove(itemToRemove);
    Context.SaveChanges();
}

5
データベースからすべてのフィールドを選択しているため、これは良い方法ではありません。
Ali Yousefi 2016年

2
これが私のやり方です。
ジャックフェアフィールド

4
@アリ、ジャック-しかし、削除しようとしているデータが実際に存在するかどうかを最初にチェックして問題を防ぐことができるので、これは好ましいと思います。受け入れられた回答自体にはチェックはありません。
マイケルフィリップス

4
これがより良い方法です。それについて考えてください。John Smithが30秒前にSusie Smithが削除したid = 1のアイテムを削除しようとしているが、Johnが知らない場合はどうなりますか?その場合、データベースにアクセスする必要があります。
勇者

4
@Yushaなんで?どちらのシナリオでも、結果はレコードがなくなっているということです。それが今起こったか30秒前に起こったかどうか、本当に気にしますか?一部の競合状態は、追跡するのがそれほど興味深いものではありません。
9Rune5 2018年

13
  var stud = (from s1 in entities.Students
            where s1.ID== student.ID
            select s1).SingleOrDefault();

  //Delete it from memory
  entities.DeleteObject(stud);
  //Save to database
  entities.SaveChanges();

2
FirstOrDefault危険です。1つしかないことを知っている(SingleOrDefaultまたはを使用する)か、1つ以上あることをループで実行する必要があります。
Mark Sowul

8
Employer employer = context.Employers.First(x => x.EmployerId == 1);

context.Customers.DeleteObject(employer);
context.SaveChanges();

ID 1のオブジェクトがない場合、これで保護されますか?例外をスローしませんか?
ジャックフェアフィールド

@JackFairfield nullオブジェクトをチェックする必要があると思います。それに従って削除を実行します。
Jawand Sing 2017

First危険です。1つしかないことを知っている(Singleまたはを使用する)か、1つ以上あることをループで実行する必要があります。
Mark Sowul

5

LINQでエンティティフレームワークを使用しています。次のコードは私にとって役に立ちました。

1-複数のレコードの場合

 using (var dbContext = new Chat_ServerEntities())
 {
     var allRec= dbContext.myEntities;
     dbContext.myEntities.RemoveRange(allRec);
     dbContext.SaveChanges();
 }

2-単一レコードの場合

 using (var dbContext = new Chat_ServerEntities())
 {
     var singleRec = dbContext.ChatUserConnections.FirstOrDefault( x => x.ID ==1);// object your want to delete
     dbContext.ChatUserConnections.Remove(singleRec);
     dbContext.SaveChanges();
 }

単一レコードの場合は、SingleOrDefault代わりに使用しないでFirstOrDefaultください。
Mark Sowul

SingleOrDefaultを使用する場合は常に、クエリの結果が最大で1つの結果になることを明確に示します。一方、FirstOrDefaultを使用する場合、クエリが結果の任意の量を返すことができますが、あなたが最初のものだけにしたいと述べているstackoverflow.com/a/1745716/3131402を
Baqer Naqvi

1
はい、それでは、複数のレコードがある場合に、任意のレコードを削除することが正しいのはなぜですか?特にこの場合、IDがキーなので、1つある必要があります。複数ある場合、それはバグです(Singleが検出します)
Mark Sowul

@MarkSowulあなたは正しいです。FirstOrDefaultを使用するように回答を編集しました。
Baqer Naqvi 2018

@BaqerNaqvi RemoveRangeは、パフォーマンスの観点からエンティティを削除するためのひどい方法です。特に、エンティティが外部キーによるすべてのナビゲーションプロパティで重い場合。私はむしろvar sql = "DELETE FROM YOUR_TABLE WHERE YOUR_FIELD = @your_parameter";を使用します。this.your_context.Database.ExecuteSqlCommand(sql、new SqlParameter( "@ your_parameter"、yourParameter));
curiousBoy 2018

2

より一般的なアプローチ

public virtual void Delete<T>(int id) where T : BaseEntity, new()
{
    T instance = Activator.CreateInstance<T>();
    instance.Id = id;
    if (dbContext.Entry<T>(entity).State == EntityState.Detached)
    {
        dbContext.Set<T>().Attach(entity);
    }

    dbContext.Set<T>().Remove(entity);
}

2

Entity Framework 6では、を使用できますRemove。またusing、接続が閉じられていることを確認するために使用するのも良い方法です。

using (var context = new EmployDbContext())
{
    Employ emp = context.Employ.Where(x => x.Id == id).Single<Employ>();
    context.Employ.Remove(emp);
    context.SaveChanges();
}

1

私が前後にバウンスした3つの方法を提供したかっただけです。

方法1:

var record = ctx.Records.FirstOrDefault();
ctx.Records.Remove(record);
ctx.SaveChanges();

方法2:

var record = ctx.Records.FirstOfDefault();
ctx.Entry(record).State = EntityState.Deleted;
ctx.SaveChanges();
ctx.Entry(record).State = EntityState.Detached;

方法2を選択する理由の1つは、EFまたはEFCoreをに設定した場合QueryTrackingBehavior.NoTrackingの方が安全であるためです。

次に、方法3があります。

var record = ctx.Records.FirstOrDefault();
var entry = ctx.Entry(record);
record.DeletedOn = DateTimeOffset.Now;
entry.State = EntityState.Modified;
ctx.SaveChanges();
entry.State = EntityState.Detached;

これは、レコードのDeletedOnプロパティを設定することによってソフト削除アプローチを利用し、レコードを将来の使用に備えて保持することができます。基本的には、ごみ箱に入れます。


また、方法3に関しては、レコード全体を変更するように設定する代わりに、

entry.State = EntityState.Modified;

また、列のみDeletedOnを変更済みとして設定するだけです。

entry.Property(x => x.DeletedOn).IsModified = true;

0
    [HttpPost]
    public JsonResult DeleteCotnact(int id)
    {
        using (MycasedbEntities dbde = new MycasedbEntities())
        {
            Contact rowcontact = (from c in dbde.Contact
                                     where c.Id == id
                                     select c).FirstOrDefault();

            dbde.Contact.Remove(rowcontact);
            dbde.SaveChanges();

            return Json(id);
        }
    }

あなたはこれをどう思うか、簡単かどうか、これを試すこともできます:

        var productrow = cnn.Product.Find(id);
        cnn.Product.Remove(productrow);
        cnn.SaveChanges();

0

ジェネリックDAOの場合、最終的にこれは次のようになります。

    public void Detele(T entity)
    {
        db.Entry(entity).State = EntityState.Deleted;
        db.SaveChanges();
    }


0

あなたはこのようにそれを簡単に行うことができます

   public ActionResult Delete(int? id)
    {
        using (var db = new RegistrationEntities())
        {
            Models.RegisterTable Obj = new Models.RegisterTable();
            Registration.DAL.RegisterDbTable personalDetail = db.RegisterDbTable.Find(id);
            if (personalDetail == null)
            {
                return HttpNotFound();
            }
            else
            {
                Obj.UserID = personalDetail.UserID;
                Obj.FirstName = personalDetail.FName;
                Obj.LastName = personalDetail.LName;
                Obj.City = personalDetail.City;

            }
            return View(Obj);
        }
    }


    [HttpPost, ActionName("Delete")]

    public ActionResult DeleteConfirmed(int? id)
    {
        using (var db = new RegistrationEntities())
        {
            Registration.DAL.RegisterDbTable personalDetail = db.RegisterDbTable.Find(id);
            db.RegisterDbTable.Remove(personalDetail);
            db.SaveChanges();
            return RedirectToAction("where u want it to redirect");
        }
    }

モデル

 public class RegisterTable
{

    public int UserID
    { get; set; }


    public string FirstName
    { get; set; }


    public string LastName
    { get; set; }


    public string Password
    { get; set; }


    public string City
    { get; set; }

} 

あなたはそれをどこから呼ぶのか

 <table class="table">
    <tr>
        <th>
            FirstName
        </th>
        <th>
            LastName
        </th>

        <th>
            City
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td> @item.FirstName </td>
            <td> @item.LastName </td>
            <td> @item.City</td>
            <td>
                <a href="@Url.Action("Edit", "Registeration", new { id = item.UserID })">Edit</a> |
                <a href="@Url.Action("Details", "Registeration", new { id = item.UserID })">Details</a> |
                <a href="@Url.Action("Delete", "Registeration", new { id = item.UserID })">Delete</a>

            </td>
        </tr>

    }

</table>

これがあなたにとって理解しやすいことを願っています


0

グリッドのclickまたはcelldoubleclickイベントでこれを行うことができます(使用した場合)

if(dgEmp.CurrentRow.Index != -1)
 {
    employ.Id = (Int32)dgEmp.CurrentRow.Cells["Id"].Value;
    //Some other stuff here
 }

次に、削除ボタンで次のようにします。

using(Context context = new Context())
{
     var entry = context.Entry(employ);
     if(entry.State == EntityState.Detached)
     {
        //Attached it since the record is already being tracked
        context.Employee.Attach(employ);
     }                             
     //Use Remove method to remove it virtually from the memory               
     context.Employee.Remove(employ);
     //Finally, execute SaveChanges method to finalized the delete command 
     //to the actual table
     context.SaveChanges();

     //Some stuff here
}

または、LINQ To Entitiesクエリを使用する代わりに、LINQクエリを使用できます。

var query = (from emp in db.Employee
where emp.Id == employ.Id
select emp).Single();

prevent.Idは、DataGridViewのCellDoubleClickイベントから既に渡されたフィルタリングパラメータとして使用されます。


コードの背後にあるアイデアは、削除するレコードのid(employ.Id)をモデル(従業員クラス)にワイヤリングし、それをコンテキストから実際のテーブルにアタッチしてから、メモリ内のRemove()メソッドを実行することです。最後に、SaveChanges()メソッドを使用して、データベースへの実際の保存を実行します。LINQクエリも正常に機能しますが、レコードのIDを取得するためだけにテーブルにクエリを実行するという考えは好きではありません。
arvin aquio

0

安全な方法は次のとおりです。

using (var transitron = ctx.Database.BeginTransaction())
{
  try
  {
    var employer = new Employ { Id = 1 };
    ctx.Entry(employer).State = EntityState.Deleted;
    ctx.SaveChanges();
    transitron.Commit();
  }
  catch (Exception ex)
  {
    transitron.Rollback();
    //capture exception like: entity does not exist, Id property does not exist, etc...
  }
}

ここで、必要なすべての変更を積み重ねることができるため、SaveChangesとCommitの前に一連の削除を実行して、すべてが成功した場合にのみ適用されるようにすることができます。


0

最善の方法は、チェックしてから削除することです

        if (ctx.Employ.Any(r=>r.Id == entity.Id))
        {
            Employ rec = new Employ() { Id = entity.Id };
            ctx.Entry(rec).State = EntityState.Deleted;
            ctx.SaveChanges();
        }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.