简体   繁体   English

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

[英]How do I save a complex C# object in the database using ADO.NET and stored procedures?

I have a complex C# object which needs to be persisted in multiple tables (around 12) in the database: 我有一个复杂的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 ...
}

Questions: 问题:

  1. What is the best way to send this complex object (an instance of Foo ) as input to the stored procedure? 将此复杂对象( Foo实例)作为输入发送到存储过程的最佳方法是什么?
  2. In the stored procedure how can I relate the corresponding Foo , Bar and Baz tables with its parent Ids (ex. Bar needs its parent FooId )? 在存储过程中,如何将相应的FooBarBaz表与其父ID相关联(例如Bar需要其父FooId )?

Here is a rough outline of how you might want to consider modeling it. 以下是您可能想要考虑建模的大致轮廓。 This isn't by any means a complete skeleton (as you may want to play with the scope a bit), but should give a general idea. 这绝不是一个完整的骨架(因为你可能想稍微使用范围),但应该给出一个大致的想法。 I've used models similar to this in several projects. 我在几个项目中使用过类似的模型。

It may be possible to abstract these classes if they all follow the same type of data model. 如果它们都遵循相同类型的数据模型,则可以抽象这些类。

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. */
}

In theory you should serialize your complex object into XML and pass it as parameter to stored procedure. 理论上,您应该将复杂对象序列化为XML并将其作为参数传递给存储过程。

In stored procedure code you can query this XML. 在存储过程代码中,您可以查询此XML。 TSQL Parse XML in Stored Procedure 存储过程中的TSQL解析XML

In result you can reach high performance, but this way may become too difficult to maintain because stored procedure must know how to proceed your complex object. 结果,您可以达到高性能,但这种方式可能变得难以维护,因为存储过程必须知道如何继续复杂对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM