Bagaimana Anda menyimpan pengaturan user.config di berbagai versi perakitan di .net?

146

Pada dasarnya masalahnya adalah bahwa setiap kali versi rakitan berubah (yaitu pengguna menginstal versi baru aplikasi) semua pengaturannya diatur ulang ke default (atau lebih tepatnya pengguna baru. File konfigurasi dibuat dalam folder dengan versi yang berbeda nomor sebagai nama)

Bagaimana saya bisa mempertahankan pengaturan yang sama ketika memutakhirkan versi, karena menggunakan file ini atau registri tampaknya tidak disarankan?

Ketika kami menggunakan Clickonce sepertinya bisa menangani ini, jadi sepertinya itu harus bisa dilakukan, tapi saya tidak yakin bagaimana caranya.

Davy8
sumber
Pertanyaan serupa ?
Allen Rice
Tidak, itu merujuk pada default untuk tidak memeriksa file ke dalam kontrol versi (atau jadi saya kumpulkan) Ini berkaitan dengan pengaturan khusus pengguna (Windows) untuk pengguna akhir
Davy8
Hanya pertanyaan yang saya butuhkan, terima kasih :)
Binary Worrier
Saya telah memposting solusi yang mungkin di utas berikut: stackoverflow.com/a/47921377/3223783 Semoga membantu!
dontbyteme
Saya telah memposting solusi yang mungkin di utas ini . Semoga itu bisa membantu!
dontbyteme

Jawaban:

236

ApplicationSettingsBase memiliki metode yang disebut Upgrade yang memigrasikan semua pengaturan dari versi sebelumnya.

Untuk menjalankan penggabungan setiap kali Anda mempublikasikan versi baru aplikasi Anda, Anda dapat menentukan boolean flag di file pengaturan Anda yang defaultnya benar. Beri nama UpgradeRequired atau yang serupa.

Kemudian, pada saat mulai aplikasi Anda memeriksa untuk melihat apakah flag sudah diatur dan jika sudah, panggil metode Upgrade , atur flag ke false dan simpan konfigurasi Anda.

if (Settings.Default.UpgradeRequired)
{
    Settings.Default.Upgrade();
    Settings.Default.UpgradeRequired = false;
    Settings.Default.Save();
}

Baca lebih lanjut tentang metode Upgrade di MSDN . The GetPreviousVersion juga mungkin layak lihat jika Anda perlu melakukan beberapa penggabungan kustom.

Markus Olsson
sumber
2
Sebuah pertanyaan kecil, apa yang merupakan versi baru? Adakah bagian dari nomor 4 bagian? Saya menggunakan ClickOnce jadi apakah itu binatang yang berbeda?
Refresh Paladin
4
Apa jenis pengaturan yang harus diupgradeRequired ? appSettings,, userSettingsatau applicationSettings? Sebagai pengaturan Pengguna pada Pengaturan. Pengaturan, sekali pertama kali diubah ke false itu tidak akan pernah benar lagi. Versi baru tidak akan mengatur ulang UpgradeRequired itu kembali ke True.
Dialex
4
@dialex Ini harus menjadi pengaturan Pengguna. Pengaturan jenis Aplikasi hanya baca. Nomor versi baru menyebabkan pengaturan ulang karena pengaturan disimpan di jalur khusus versi.
Leonard Thieu
4
Saya pikir saya menjawab pertanyaan saya sendiri. Jika versi sebelumnya dari file pengaturan ada, itu akan menyalin nilainya ke versi terbaru setiap kali aplikasi dijalankan, mungkin bukan yang Anda inginkan!
Hugh Jeffner
1
Saya agak terkejut bahwa ini bukan hanya perilaku standar; jika pengaturan aplikasi adalah nol saat mulai dan ia menemukan banyak pengaturan sebelumnya, ia memuatnya.
SteveCinq
3

Saya tahu ini sudah beberapa saat ... Dalam aplikasi winforms, panggil saja My.Settings.Upgrade()sebelum Anda memuatnya. Ini akan mendapatkan pengaturan terbaru, apakah versi saat ini atau versi sebelumnya.

tinlyx
sumber
2

Inilah penelitian saya jika ada orang lain yang mengalami kesulitan dengan pengaturan migrasi yang telah diubah / dihapus. Masalah mendasarnya adalah itu GetPreviousVersion()tidak berfungsi jika Anda telah mengganti nama atau menghapus pengaturan di versi baru aplikasi Anda. Jadi Anda perlu menyimpan pengaturan di Settingskelas Anda , tetapi tambahkan beberapa atribut / artefak ke dalamnya sehingga Anda tidak secara tidak sengaja menggunakannya dalam kode di tempat lain, membuatnya usang. Pengaturan sampel usang akan terlihat seperti ini di VB.NET (dapat dengan mudah diterjemahkan ke C #):

<UserScopedSetting(),
DebuggerNonUserCode(),
DefaultSettingValue(""),
Obsolete("Do not use this property for any purpose. Use YOUR_NEW_SETTING_NAME instead."),
NoSettingsVersionUpgrade()>
Public Property OldSettingName() As String
  Get
    Throw New NotSupportedException("This property is obsolete")
  End Get
  Set
    Throw New NotSupportedException("This property is obsolete")
  End Set
End Property

Pastikan Anda menambahkan properti ini ke namespace / kelas yang sama yang memiliki pengaturan aplikasi Anda. Di VB.NET, kelas ini dinamai MySettingsdan tersedia di Mynamespace. Anda dapat menggunakan fungsionalitas kelas parsial untuk mencegah pengaturan usang Anda mencampur dengan pengaturan Anda saat ini.

Penghargaan penuh untuk jsharrison karena memposting artikel yang bagus tentang masalah ini. Anda dapat membaca detail lebih lanjut di sana.

dotNET
sumber
1

Berikut adalah variasi pada solusi yang disajikan di sini yang merangkum logika upgrade ke kelas abstrak yang berasal dari kelas pengaturan.

Beberapa solusi yang diajukan menggunakan atribut DefaultSettingsValue untuk menentukan nilai yang menunjukkan kapan pengaturan sebelumnya tidak dimuat. Preferensi saya adalah cukup menggunakan jenis yang nilai standarnya menunjukkan ini. Sebagai bonus, DateTime? sangat membantu informasi debug.

public abstract class UserSettingsBase : ApplicationSettingsBase
{
    public UserSettingsBase() : base()
    {
        // Accessing a property attempts to load the settings for this assembly version
        // If LastSaved has no value (default) an upgrade might be needed
        if (LastSaved == null)
        {
            Upgrade();
        }
    }

    [UserScopedSetting]
    public DateTime? LastSaved
    {
        get { return (DateTime?)this[nameof(LastSaved)]; }
        private set { this[nameof(LastSaved)] = value; }
    }

    public override void Save()
    {
        LastSaved = DateTime.Now;
        base.Save();
    }
}

Turun dari UserSettingsBase:

public class MySettings : UserSettingsBase
{
    [UserScopedSetting]
    public string SomeSetting
    {
        get { return (string)this[nameof(SomeSetting)]; }
        set { this[nameof(SomeSetting)] = value; }
    }

    public MySettings() : base() { }
}

Dan gunakan itu:

// Existing settings are loaded and upgraded if needed
MySettings settings = new MySettings();
...
settings.SomeSetting = "SomeValue";
...
settings.Save();
jeff krueger
sumber
0

Jika perubahan Anda ke pengaturan pengguna dilakukan secara terprogram, bagaimana dengan mempertahankan salinan (hanya) modifikasi pada pengguna. Pengaturan dalam file terpisah, misalnya pengaturan pengguna.customized.settings?

Anda mungkin masih ingin mempertahankan dan memuat pengaturan yang diubah di pengaturan pengguna juga. Tetapi dengan cara ini ketika Anda menginstal versi aplikasi Anda yang lebih baru dengan versi pengguna yang lebih baru. Anda dapat menanyakan kepada pengguna apakah mereka ingin terus menggunakan pengaturan yang dimodifikasi dengan menyalinnya kembali ke pengaturan pengguna yang baru. Anda dapat mengimpornya secara grosir, atau membeli toko dan meminta pengguna untuk mengonfirmasi pengaturan mana yang ingin terus mereka gunakan.

EDIT: Saya membaca terlalu cepat pada bagian "lebih akurat" tentang versi perakitan yang menyebabkan pengguna baru. Pengaturan dipasang ke direktori khusus versi baru. Jadi, ide di atas mungkin tidak membantu Anda, tetapi mungkin menyediakan beberapa bahan untuk dipikirkan.

JMD
sumber
0

Beginilah cara saya menanganinya:

public virtual void LoadSettings(ServiceFileFormBaseSettings settings = null, bool resetSettingsToDefaults = false)
{
    if (settings == null)
            return;

    if (resetSettingsToDefaults)
        settings.Reset();
    else
    {
        settings.Reload();

        if (settings.IsDefault)
            settings.Upgrade();
    }

    this.Size = settings.FormSize;

}

dan di kelas pengaturan, saya mendefinisikan properti IsDefault:

// SaveSettings always sets this to be FALSE.
// This will have the default value TRUE when first deployed, or immediately after an upgrade.
// When the settings exist, this is false.
//
[UserScopedSettingAttribute()]
[DefaultSettingValueAttribute("true")]
public virtual bool IsDefault
{
    get { return (bool)this["IsDefault"]; }
    set { this["IsDefault"] = value; }
}

Di SaveSettings, saya mengatur IsDefault ke false:

public virtual void SaveSettings(ServiceFileFormBaseSettings settings = null)
{
    if (settings == null) // ignore calls from this base form, if any
        return;

    settings.IsDefault = false;
    settings.FormSize = this.Size;
    settings.Save();
}
Ian
sumber