Pertanyaan Hidrat sifat string yang tidak diperlukan dari nol ke string kosong


Jika saya memiliki kelas model

public class Foo
{
    public string Property1 { get; set; } = string.Empty;
    ... other properties omitted for brevity
}

Ini akan menyimpan ke database sebagai null karena bukan properti yang dibutuhkan. Tetapi sekarang ketika saya mengambil entitas bahwa properti adalah null. Saya memiliki banyak properti string yang tidak diperlukan pada entitas ini dan saya tidak ingin harus melakukan banyak pemeriksaan null pada properti tersebut, saya hanya ingin mereka direhidrasi sebagai string kosong jika mereka null dalam database. Saya tidak keberatan mereka disimpan di db sebagai null tetapi ketika entitas diambil dari db saya ingin memilikinya dipetakan kembali ke string kosong jika null di db.

Saya pikir ini harus menjadi skenario yang cukup umum dan bertanya-tanya apakah saya kehilangan beberapa cara sederhana untuk melakukannya dengan pengaturan konfigurasi atau sesuatu. Saya cukup baru menggunakan EF.

Di OnModelCreating saya untuk properti ini saya punya:

.HasMaxLength(50)
.HasDefaultValue(string.Empty)

tetapi masih disimpan sebagai null dan rehidrasi sebagai null. Sekali lagi saya tidak keberatan disimpan sebagai nol tetapi saya ingin itu terhidrasi sebagai string kosong jika tidak null dalam db.

Saya mencoba memodifikasi kelas model seperti ini:

private string property1 = string.empty;
public string Property1
{
    get { return property1; }
    set { property1 = value ?? string.Empty; }
} 

berpikir bahwa EF harus menggunakan setter tetapi ini masih menghasilkan properti null. Sejauh ini satu-satunya cara saya bisa menyelesaikannya dengan membuat properti seperti ini:

private string property1 = string.empty;
public string Property1
{
    get { return property1 ?? string.empty; }
    set { property1 = value ?? string.Empty; }
} 

Saya lebih suka tidak harus membuat semua properti saya seperti itu.

Adakah yang bisa menyarankan cara yang lebih bersih untuk melakukan ini atau mengoreksi saya jika saya melakukan sesuatu yang salah atau tidak biasa atau memikirkannya salah. Apakah saya kehilangan beberapa cara yang lebih mudah untuk mencapai ini?

Saya tidak ingin membuat properti yang diperlukan karena string kosong tidak akan memuaskan kasus itu juga.


6
2017-12-07 17:45


asal


Jawaban:


Versi Entity Framework asli pertanyaannya adalah EF7, versi ef-core pertama yang diubah namanya menjadi EF-core 1 nanti. Perilaku yang dijelaskan sangat berbeda dari versi EF-core saat ini (2.1.1).

Izinkan saya menyebutkan dua poin utama:

1

Ini akan menyimpan ke database sebagai null karena bukan properti yang dibutuhkan. Tetapi sekarang ketika saya mengambil entitas bahwa properti adalah null.

Bukan itu yang terjadi saat ini.

Ikuti kelas sederhana:

public class Item
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Code { get; set; } = string.Empty;
}

Saat menambahkan Item hanya dari itu Name diatur, SQL berikut dijalankan:

exec sp_executesql N'SET NOCOUNT ON;
INSERT INTO [Items] ([Code], [Name])
VALUES (@p0, @p1);
SELECT [ID]
FROM [Items]
WHERE @@ROWCOUNT = 1 AND [ID] = scope_identity();

',N'@p0 nvarchar(4000),@p1 nvarchar(50)',@p0=N'',@p1=N'Item1'

String kosong adalah bagian dari pernyataan insert. Juga, ketika mengambil item dari database, itu Code adalah string kosong.

2

Di OnModelCreating saya untuk properti ini saya punya:

.HasMaxLength(50)
.HasDefaultValue(string.Empty)

tetapi masih disimpan sebagai null dan rehidrasi sebagai null.

Itu pun berbeda sekarang. Ambil kelas yang sama tetapi sekarang dengan:

    public string Code { get; set; }  // removed "= string.Empty;"

... dan pemetaan untuk Code:

modelBuilder.Entity<Item>().Property(p => p.Code).HasMaxLength(50).HasDefaultValue(string.Empty);

... Maka ini adalah tabel yang dihasilkan:

CREATE TABLE [Items] (
    [ID] int NOT NULL IDENTITY,
    [Name] nvarchar(50) NOT NULL,
    [Code] nvarchar(50) NULL DEFAULT N'', -- Default constraint
    CONSTRAINT [PK_Items] PRIMARY KEY ([ID])
);

Seperti yang Anda lihat, instruksi pemetaan diterjemahkan ke dalam database default.

Saat menambahkan Item hanya dari itu Name diatur, SQL berikut dijalankan:

exec sp_executesql N'SET NOCOUNT ON;
INSERT INTO [Items] ([Name])
VALUES (@p0);
SELECT [ID], [Code]
FROM [Items]
WHERE @@ROWCOUNT = 1 AND [ID] = scope_identity();

',N'@p0 nvarchar(50)',@p0=N'Item1'

Jadi EF menyisipkan item dan membaca kembali nilai default yang dibuat agar entitas yang dilacak sinkron dengan database. Demikian juga, item yang dibaca dari database kemudian memiliki string kosong Code.

Temuan ini menegaskan bahwa EF7 adalah versi yang sangat belum matang dari EF-core (meskipun saya tidak mengkonfirmasi bahwa itu benar-benar menampilkan perilaku yang dijelaskan). Ada lebih banyak, dan lebih mendalam, yang memecahkan perubahan sejak itu. Saya harap kita akan segera melupakan tentang versi EF-core awal ini. Sejak versi 2.0, EF-core akhirnya berkembang menjadi ORM siap produksi.


2
2017-07-24 11:28