You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# MVC设备配置保存问题:生成新ConfigId与递增VersionNr求助

Hey Roland, let's break down how to fix and optimize your device configuration system—sounds like you're dealing with versioning and batch config line management, which are super common gotchas. Let's start with the core issues and actionable solutions based on what you described.

Core Fixes & Optimizations for Your Configuration System

1. Ensure New config_id & Proper VersionNr Increment on Save

The biggest mistake here is likely modifying existing configuration records instead of creating full new versions. You need to preserve historical configs, so every save should generate a fresh set of entries tied to a new config_id and incremented VersionNr.

Key Code Adjustment Example

Assuming your Device entity links to multiple Device_Pricelist versions, here's how to safely generate new versions:

public ActionResult Edit(int? Id)
{
    if (Id == null) return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    
    var targetDevice = db.Devices.Find(Id);
    if (targetDevice == null) return HttpNotFound();

    // Get the latest version number for the device (start at 0 if no versions exist)
    int latestVersion = db.Device_Pricelist
        .Where(dp => dp.DeviceId == Id)
        .Select(dp => dp.VersionNr)
        .DefaultIfEmpty(0)
        .Max();

    // Fetch modified config lines from your form/view model
    var userModifiedLines = /* Bind from request data, e.g., using a ViewModel */;

    // Generate new config_id (use database auto-increment if possible, or manual max+1)
    int newConfigId = db.Device_Pricelist.Max(dp => dp.Config_ID) + 1;
    int newVersionNr = latestVersion + 1;

    // Create new config entries for the new version
    foreach (var line in userModifiedLines)
    {
        var newConfigEntry = new Device_Pricelist
        {
            Config_ID = newConfigId,
            DeviceId = Id.Value,
            VersionNr = newVersionNr,
            // Copy all relevant config fields from the user's input
            Price = line.Price,
            DeviceType = line.DeviceType,
            // ... other config properties
        };
        db.Device_Pricelist.Add(newConfigEntry);
    }

    db.SaveChanges();
    return RedirectToAction("Index");
}

2. Handle Bulk Add/Delete of Config Lines

When users add or remove lines, remember:

  • Don't delete historical config lines: Instead, exclude marked-for-delete lines from the new version.
  • Use a ViewModel to simplify binding: Avoid directly passing entities between your view and controller.

Example ViewModel for Clean Binding

public class DeviceConfigEditViewModel
{
    public int DeviceId { get; set; }
    public List<ConfigLineViewModel> ConfigLines { get; set; } = new();
}

public class ConfigLineViewModel
{
    public int? ExistingLineId { get; set; } // Null = new line
    public bool IsMarkedForDelete { get; set; } // For user-deleted lines
    public decimal Price { get; set; }
    public string DeviceType { get; set; }
    // ... other config fields
}

Updated Post Method to Handle Bulk Changes

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(DeviceConfigEditViewModel model)
{
    if (!ModelState.IsValid) return View(model);

    using (var transaction = db.Database.BeginTransaction())
    {
        try
        {
            // Re-fetch latest version inside the transaction to avoid concurrency issues
            int latestVersion = db.Device_Pricelist
                .Where(dp => dp.DeviceId == model.DeviceId)
                .Select(dp => dp.VersionNr)
                .DefaultIfEmpty(0)
                .Max();

            int newConfigId = db.Device_Pricelist.Max(dp => dp.Config_ID) + 1;
            int newVersionNr = latestVersion + 1;

            // Only add lines that aren't marked for deletion
            foreach (var line in model.ConfigLines.Where(l => !l.IsMarkedForDelete))
            {
                db.Device_Pricelist.Add(new Device_Pricelist
                {
                    Config_ID = newConfigId,
                    DeviceId = model.DeviceId,
                    VersionNr = newVersionNr,
                    Price = line.Price,
                    DeviceType = line.DeviceType
                });
            }

            db.SaveChanges();
            transaction.Commit();
        }
        catch (Exception ex)
        {
            transaction.Rollback();
            ModelState.AddModelError("", "Another user updated this config. Please refresh and try again.");
            return View(model);
        }
    }

    return RedirectToAction("Index");
}

3. Fix Concurrency Issues for VersionNr

If multiple users edit the same device's config at once, you might get duplicate VersionNr values. The transaction above helps, but you can also add a unique constraint on (DeviceId, VersionNr) in your database to enforce version uniqueness.

4. Database Structure Optimization

For better scalability and clarity, split config metadata from line items:

-- Table to track config versions (metadata only)
CREATE TABLE DeviceConfigVersions (
    Config_ID INT PRIMARY KEY IDENTITY,
    DeviceId INT FOREIGN KEY REFERENCES Devices(Id),
    VersionNr INT NOT NULL,
    CreatedAt DATETIME DEFAULT GETDATE(),
    CreatedBy NVARCHAR(50),
    UNIQUE(DeviceId, VersionNr) -- Prevent duplicate versions per device
)

-- Table for individual config lines (linked to a version)
CREATE TABLE Device_Pricelist (
    LineId INT PRIMARY KEY IDENTITY,
    Config_ID INT FOREIGN KEY REFERENCES DeviceConfigVersions(Config_ID),
    Price DECIMAL(18,2),
    DeviceType NVARCHAR(50),
    -- ... other config fields
)

This makes it easier to query historical versions and keeps your data organized.

内容的提问来源于stack exchange,提问作者Roland_dfa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:50:35