2017-04-19 1 views
0

私が間違った条件を使用した場合、まずはご容赦ください。非常に PostgreSQLとNoSQLスタイルのデータストレージの両方に新しいものです。移動先:自動増分フィールドを含むJSON列をPostgresに挿入しますか?

私は、.NETプロジェクトをPostgreSQLデータベースに接続するためにnpgsqlを使用しています。 NoSQLのドキュメントストレージとして使用しています。テーブルはプライマリキーidの列とdataの列のjsonbオブジェクトで構成されています。

dataの列では、各挿入に自動的にインクリメントするidフィールドを生成する方法も必要です。このIDは必ずしもプライマリキーと一致する必要はありませんが、それは私が働いている前提の一種です。

私は次のスクリプトを使用して、pgAdminで、この作品を作ることができました:

drop table public.testjson; 
 
drop sequence public.testjson_id_seq; 
 

 
CREATE SEQUENCE public.testjson_id_seq 
 
    INCREMENT 1 
 
    MINVALUE 1 
 
    MAXVALUE 9223372036854775807 
 
    START 1 
 
    CACHE 1; 
 
ALTER TABLE public.testjson_id_seq 
 
    OWNER TO login; 
 

 
CREATE TABLE public.testjson 
 
(
 
    id bigint NOT NULL DEFAULT nextval('testjson_id_seq'::regclass), 
 
    data jsonb, 
 
    CONSTRAINT testjson_pkey PRIMARY KEY (id) 
 
); 
 
ALTER TABLE public.testjson 
 
    OWNER TO login; 
 

 

 
-- Insert data using currval -- 
 
INSERT INTO testjson (data) VALUES(to_jsonb('{"jsonid": '||currval('testjson_id_seq'::regclass)::bigint||', moreStuff: "all the stuff!"}')); 
 
INSERT INTO testjson (data) VALUES(to_jsonb('{"jsonid": '||currval('testjson_id_seq'::regclass)::bigint||', moreStuff: "all the stuff!"}')); 
 
INSERT INTO testjson (data) VALUES(to_jsonb('{"jsonid": '||currval('testjson_id_seq'::regclass)::bigint||', moreStuff: "all the stuff!"}')); 
 
INSERT INTO testjson (data) VALUES(to_jsonb('{"jsonid": '||currval('testjson_id_seq'::regclass)::bigint||', moreStuff: "all the stuff!"}')); 
 
select * from testjson 
 

 
-- Output -- 
 

 
id | data 
 
--------------------------------------------------------- 
 
1 | "{\"jsonid\": 1, moreStuff: \"all the stuff!\"}" 
 
2 | "{\"jsonid\": 2, moreStuff: \"all the stuff!\"}" 
 
3 | "{\"jsonid\": 3, moreStuff: \"all the stuff!\"}" 
 
4 | "{\"jsonid\": 4, moreStuff: \"all the stuff!\"}"
これまでのところ、とても良いです。私はこれをリファクタリングするつもりだと思うので、jsonidフィールドには独自のシーケンスがあり、 currvalの代わりに nextval(重複を引き起こす競合状態を防ぐため)を使用しますが、それに関する問題はありません。私はコード側でこれを複製するのに問題があります。

var crcmd = new NpgsqlCommand("INSERT INTO "+_schema+"."+table+" ("+JsonColumn+") VALUES (:json) RETURNING id;", _conn); 
 

 
var jsonData = getSerializedJsonData(thing, primaryKey); 
 
crcmd.Parameters.AddWithValue("json", NpgsqlDbType.Jsonb, jsonData); 
 

 
returnId = (long) crcmd.ExecuteScalar(); 
 

 
... 
 

 
private string getSerializedJsonData<T>(T thing, string primaryKey, string tableSeq) 
 
{ 
 
    var jsonThing = JsonConvert.SerializeObject(thing); 
 

 
    var bracketIndex = jsonThing.IndexOf('{'); 
 
    var thingPrefix = jsonThing.Substring(0, bracketIndex + 1); 
 
    var thingData = jsonThing.Substring(bracketIndex + 1); 
 
    var pkEntry = "\"" + primaryKey +"\": currval('" + tableSeq + '::regclass)::bigint, "; 
 
    jsonThing = thingPrefix + pkEntry + thingData; 
 
    return jsonThing; 
 
}

しかし、私はそれをテストしようとすると、次の例外がスローされます:ここでは他のquestionsで周りを見ると、これはうまくいくかもしれないことを信じるように私を導い

Npgsql.PostgresException: 22P02: invalid input syntax for type json; Token "currval" is invalid

私が間違っているのは何ですか?

答えて

0

私はそれを得ました。私が修正する必要があった2つのことが分かった。

最初のものはjsonbへの変換でした。前に気付かなかったのですが、postgresの出力を見ると、dataの列がjsonbオブジェクトではなく文字列として保存されています。これはto_jsonb('...')('...')::jsonbに置き換えることで簡単に修正されます。

2番目のタスクは、C#で動作させることでした。そのためには、の作成方法を変更する必要がありました。currvalの値にアクセスするには、コマンドテキストを元のテキストとして渡す必要がありました。 。文字列は、データベースの鉄則を破っとして直接クエリにデータを挿入

var jsonData = getSerializedJsonData(thing, primaryKey); 
 
var crcmd = new NpgsqlCommand("INSERT INTO "+_schema+"."+table+" ("+JsonColumn+") VALUES (('+jsonData+')::jsonb) RETURNING id;", _conn); 
 

 
returnId = (long) crcmd.ExecuteScalar(); 
 

 
... 
 

 
private string getSerializedJsonData<T>(T thing, string primaryKey, string tableSeq) 
 
{ 
 
    var jsonThing = JsonConvert.SerializeObject(thing); 
 

 
    var bracketIndex = jsonThing.IndexOf('{'); 
 
    var thingPrefix = jsonThing.Substring(0, bracketIndex + 1); 
 
    var thingData = jsonThing.Substring(bracketIndex + 1); 
 
    var pkEntry = "\"" + primaryKey +"\": currval('" + tableSeq + '::regclass)::bigint, "; 
 
    jsonThing = thingPrefix + pkEntry + thingData; 
 
    return jsonThing; 
 
} 
 

 
-- Output (truncated) -- 
 
id | data 
 
-------------------------------------------------------- 
 
1 | { IsActive: true, "DisplayName": "configUser", "UserLoginId": 1", "PasswordHash":... 
 
2 | { IsActive: true, "DisplayName": "WDCGVBNESSAULSAZLIVR", "UserLoginId": 2", "Pass... 
 
3 | { IsActive: false, "DisplayName": "UJMFANMOSHPNDQSEUEGL", "UserLoginId": 3", "Pas... 
 
4 | { IsActive: true, "DisplayName": "SOQDFTZVHPHXIXDVQJTS", "UserLoginId": 4", "Pass... 
 
5 | { IsActive: true, "DisplayName": "WFPUMCRBRPDHSQALMKPW", "UserLoginId": 5", "Pass... 
 
6 | { IsActive: true, "DisplayName": "HVBEGQSSFJWCJYCCLMXI", "UserLoginId": 6", "Pass...

+0

:だから、最終的な、作業のコードは、より多くのこのようになります。あなたはもっと良い解決策を見つけましたか? – piojo

関連する問題