简体   繁体   中英

implement updateable recordsets in c#

What would it take to implement an updateable recordset in c#? Think what is available for Sql CE, but implemented for others like Sql Server. Do the recordset classes basically implement 99% of this and would just need some tinkering to get it added, or would this be a big undertaking? Perhaps using some code from Mono and extending it?

Just fyi, one of the early betas of .net 1.1 (if I have my versions correct) actually did implement this, but was later removed due to fear of abuse. Valid concern, but it sure would be handy in certain scenarios.

There is no component available to imitate a scrollable cursor that produces and update over a live connection. And for some very good reasons that are far from being abused. Not least of which is the fact that it's a very poor use of resources on the SQL Server.

Yes, the SqlDataReader does provide a fast-forward and read-only version of a query. Further, the reader only retrieves one row at a time and leaves the connection open the entire time. This allows you to fetch through a very large result set and leave the resources on the SQL Server, and you can do it very quickly.

However, the process of making that a live feed back to the SQL Server can be simulated pretty easily. And to do this I'm going to recommend Dapper , for two reasons:

  1. It's performance is unrivaled.
  2. It's very light weight and easy to use.

Let's keep it simple first...

First let's start with a very simple example, so let's assume I have a table:

CREATE TABLE Foo (
    ID INT PRIMARY KEY IDENTITY(1, 1),
    Field1 FLOAT,
    Field2 VARCHAR(50)
)

so now let's get some data from Foo , but before we can we need a simple model to put it into:

public class Foo
{
    public int ID { get; set; }
    public float Field1 { get; set; }
    public string Field2 { get; set; }
}

and now we just need to get some data:

using Dapper;

...

public void ReadFoo()
{
    IDbConnection conn = new SqlConnection("[some connection string]");
    conn.Open();
    var list = conn.Query<Foo>("SELECT * FROM Foo");

    // and now you have a list of Foo objects you can iterate against
}

Now let's update the data yeah?

Alright, so now that we know how to get data using Dapper, let's see how we might simulate a live stream to the database yeah? So first let's build a base class:

public class DapperModelBase
{
    public abstract string PKField { get; }

    protected void OnPropertyValueChanged(string propertyName, object val)
    {
        var sql = string.Format("update {0} set {1} = @value where {2} = @id",
            this.GetType().Name,
            propertyName,
            this.PKField);

        IDbConnection conn = new SqlConnection("[some connection string]");
        conn.Execute(sql, new
            {
                value = val,
                id = this.GetType().GetProperty(this.PKField).GetValue(this, null)
            });
    }
}

so now we need to modify the Foo class just a tidge:

public class Foo
{
    // implement the abstract property
    public string PKField { get { return "ID"; } }
    public int ID { get; set; }

    private float _field1;
    public float Field1
    {
        get { return _field1; }
        set
        {
            _field1 = value;
            OnPropertyValueChanged("Field1", value);
        }
    }

    private string _field2;
    public string Field2
    {
        get { return _field2; }
        set
        {
            _field2 = value;
            OnPropertyValueChanged("Field2", value);
        }
    }
}

so now when we update an editable property while iterating we are sending back commands to make this a live feed:

// and now you have a list of Foo objects you can iterate against
foreach (var foo in list)
{
    ...
    ...
    foo.Field1 = 123f; // sends an update
    ...
    ...
    foo.Field2 = "Hello World!" // sends an update
}

now, let's take this one step further, and let's assume that the result set you're getting back is massive , and when I say that I mean 100's of MB. Well, Dapper can handle that too, simply change the line that gets data from:

var list = conn.Query<Foo>("SELECT * FROM Foo");

to:

var list = conn.Query<Foo>("SELECT * FROM Foo", buffered: false);

but nothing else changes!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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