Mengembalikan Fungsi‹Tugas› di tengah blok Menggunakan

Saya ingin mengembalikan Func di tengah blok penggunaan. Haruskah saya khawatir untuk membuangnya, sebelum pengguna menjalankan Fungsi hasilnya?

Contoh kode:

private IDbContextTransaction _transaction;

public Func<Task> BeginTransaction()
{
    Task lockDispose = CommitTransaction();
    using (_transaction = _dbContext.Database.BeginTransaction())
    {
        return async() =>
        {
            await lockDispose;
        };
        Task.WaitAll(lockDispose); //This code is unreachable.
    }
}

private async Task CommitTransaction()
{
    _transaction.Commit();
    await Task.CompletedTask;
}

Perhatikan bahwa waktu eksekusi hasil Func terserah pengguna layanan ini.

Saya memeriksa Pertanyaan Ini dan itu bukan jawaban saya.


person FarhadGh    schedule 20.12.2020    source sumber
comment
Ketika fungsi dikembalikan, transaksi akan dibuang sementara tugas di dalam fungsi sudah berjalan. Itu mungkin bukan yang Anda inginkan, dilihat dari nama metode Anda? Anda perlu menentukan dengan lebih tepat apa yang ingin Anda capai.   -  person Mo B.    schedule 20.12.2020
comment
Saya ingin menunda pembuangan sampai pengguna memutuskan untuk menjalankan fungsi hasil   -  person FarhadGh    schedule 20.12.2020
comment
Bisakah Anda menyertakan contoh bagaimana Anda ingin menggunakan metode BeginTransaction?   -  person Theodor Zoulias    schedule 20.12.2020
comment
Saya ingin mencapai tujuan ini: 1. Tidak ada yang bisa melakukan transaksi dua kali (Jadi saya menyembunyikan CommitTransaction) 2. Jangan memaksa pengguna menggunakan blok (atau menggunakan satu baris) 3. Pengguna dapat melakukan apa saja dengan dbContext dan beberapa saveChanges sebelumnya melakukan transaksi __ Juga penggunaan default untuk kasus saya adalah di middleware, sebelum dan sesudah 'menunggu selanjutnya(konteks);'   -  person FarhadGh    schedule 20.12.2020
comment
Tapi saya tidak bisa mencapai tujuan ini. Sayangnya, saya mengembalikan Transaksi dari layanan.   -  person FarhadGh    schedule 20.12.2020
comment
Menurut saya, memberikan nilai pengembalian Func<Task> kepada pengguna tidak berarti atau nyaman. Jika Anda tidak ingin mereka melakukan transaksi dua kali, Anda dapat memberi mereka fasad Transaction dengan metode CommitTransaction yang paling banyak memanggil Transaction.CommitTransaction yang sebenarnya.   -  person Theodor Zoulias    schedule 21.12.2020


Jawaban (1)


Karena Anda ingin pengguna Anda dapat bekerja dengan koneksi antara panggilan BeginTransaction dan CommitTransaction, maka satu-satunya hal yang dapat Anda lakukan adalah memindahkan pembuangan ke luar cakupan ini:

private IDbContextTransaction _transaction;

public Func<Task> BeginTransaction()
{
    _transaction = _dbContext.Database.BeginTransaction()
    return CommitTransaction;
}

private async Task CommitTransaction()
{
    _transaction.Commit();
    _transaction.Dispose();
    await Task.CompletedTask;
}

// I advice you implement IDisposable fully, but 
// this will do for the sake of demonstration
public void Dispose()
{
    _transaction?.Dispose();
}

Dan kemudian di suatu tempat di luar Anda perlu melakukan sesuatu seperti:

using (var obj = TheWayYouInitializeYourObject())
{
    var commit = obj.BeginTransaction();
    // DO WORK
    await commit();
}

or

try
{
    var commit = obj.BeginTransaction();
    // DO WORK
    await commit();
}
finally
{
    obj.Dispose();
}

Pada dasarnya, using Anda tidak dapat menjangkau kesenjangan tempat pengguna Anda bekerja, jadi mereka harus melakukannya sendiri.

Biasanya merupakan ide bagus untuk membuat benda-benda yang harus digunakan dengan bahan sekali pakai juga dapat dibuang.

person Heagon    schedule 20.12.2020
comment
Saya ragu setelah memanggil BeginTransaction(), transaksi dimulai. Dan pengguna harus bekerja dengan dbContext setelah itu. Saya akan menguji solusi Anda dan akan datang lagi untuk memperbarui komentar ini. - person FarhadGh; 20.12.2020
comment
@FarhadGh Memperbarui jawabannya. - person Heagon; 20.12.2020