c# - 如何使用 ADO.NET 和存储过程在数据库中保存复杂的 C# 对象?

标签 c# sql sql-server stored-procedures ado.net

我有一个复杂的 C# 对象,它需要保存在数据库的多个表(大约 12 个)中:

class Foo
{
    public Guid FooId { get; set; }
    public Bar[] Bars { get; set; }
}

class Bar
{
    public Guid BarId { get; set; }
    public Guid FooId { get; set; }
    public Baz[] Bazs { get; set; }
}

class Baz
{
    public Guid BazId { get; set; }
    public Guid BarId { get; set; }
    // And so on ...
}

问题:

  1. 将这个复杂对象(Foo 的一个实例)作为输入发送到存储过程的最佳方法是什么?
  2. 在存储过程中,如何将相应的 FooBarBaz 表与其父 ID(例如 Bar 需要其父 FooId)?

最佳答案

以下是您可能要考虑如何对其进行建模的粗略概述。这绝不是一个完整的框架(因为您可能想稍微玩一下示波器),但应该给出一个总体思路。我在几个项目中使用过与此类似的模型。

如果这些类都遵循相同类型的数据模型,则有可能抽象这些类。

class Foo
{
    public Guid FooId { get; private set; } // Only allow the object to define its Id.
    public List<Bar> Bars { get; set; } // Use a dynamic storage object.
    private bool Deleted { get; set; } // Monitors if the object has been deleted in the DB.

    public Foo()
    {
        this.FooId = Guid.Empty;
        this.Deleted = false;
        Bars = new List<Bar>();
    }

    public Foo(Guid fooId)
    {
        this.Deleted = false;

        this.FooId = fooId;
        LoadFromDatabase();

        Bars = new List<Bar>();
        LoadBarsFromDatabase();
    }

    private void LoadFromDatabase()
    {
        // Read from DB, set local variables...
    }

    private void LoadBarsFromDatabase()
    {
        // Psuedocode to load all Bars.
        foreach (var barData in barIdsLinkedToFooTable.Rows)
        {
            Bars.Add(new Bar(this, barData["barId"]));
        }
    }

    public void SaveToDatabase()
    {
        // If FooId is Guid.Empty, the record is new.
        // You may also want to consider the Deleted property value.
        // Either generate the new Guid first or let SQL do it for you in your SP.

        // Save Foo to DB with stored proc.

        // Save Bars.
        foreach (var bar in Bars)
        {
            bar.SaveToDatabase();
        }
    }

    public void Delete()
    {
        // Delete via a stored proc.
        // Might be a good idea to set SQL to cascade the delete,
        //  this way all the children will be deleted automatically.

        this.Deleted = true;
    }
}

class Bar
{
    public Guid BarId { get; private set; } // Only allow the local object to generate Id.
    public Foo ParentFoo { get; set; } // Store a reference to the parent.
    public List<Baz> Bazs { get; set; } // Use a dynamic storage object.
    private bool Deleted { get; set; } // Monitors if the object has been deleted in the DB.

    public Bar(Foo parentFoo)
    {
        // New Bar object.
        this.BarId = Guid.Empty;
        this.ParentFoo = parentFoo;
        this.Bazs = new List<Baz>();
        this.Deleted = false;
    }

    public Bar(Foo parentFoo, Guid barId)
    {
        // Create from existing object.
        this.Deleted = false;

        this.BarId = barId;
        this.ParentFoo = parentFoo;
        LoadFromDatabase();

        Bazs = new List<Baz>();
        LoadBazsFromDatabase();
    }

    /* DB methods for load, save, and delete similar to above. */
}

关于c# - 如何使用 ADO.NET 和存储过程在数据库中保存复杂的 C# 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27643841/

相关文章:

c# - 访问者方法中的上下文为子表达式返回 null

c# - asp.net MVC路由错误404

c# - 如何将通用数组转换为另一种类型?

sql - 在 Visual Studio 中复制列标题以及查询结果

sql 减去日期

c# - 无法使用 C# 驱动程序过滤 MongoDB 中的日期字段

mysql - 在任何 1 小时的时间间隔内选择计数 > 1 的数据

sql - 在 SQL Server 2005 中使用 SSIS 从平面文件导入时如何保留 NULL 值

python - 既不是 GROUPED 也不是 AGGREGATED 的列 X - StandardSQL/BigQuery

mysql - 如何从mysql数据库获取当前时间的数据