C# 使用 SqlKata 从动态对象到 SQL Insert 语句(或者只是 ADO.NET)
C# Getting from dynamic object to SQL Insert statement using SqlKata (or alternatively just ADO.NET)
请耐心等待,我已经工作了几个小时,感觉自己开始感到疲倦,犯了错误,并且看不到我应该看到的东西。如果这是一个愚蠢的问题,我深表歉意。我有一个动态对象循环。这些动态对象可以具有不同的形状,并且最终将被插入到与动态对象属性的列名称相匹配的数据库 table 中。因此,如果对象具有 'Title=Mr',则数据库中将有一个名为 'Title' 的数据库列。
我有下面的循环,我试图以某种方式将我的动态对象转换成一个列名数组和一个值数组,然后以某种方式在我的 Insert 语句中使用它们到 SQL 服务器使用 SqlKata (我愿意接受普通旧 ADO.NET 中的解决方案)。
然而,它严重损坏,我认为压力让我看不到像这样转动动态对象的更简单的解决方案:
{
"TRS_KEY": 712134,
"TRS_PTR": 16974,
"TailFlags": 0,
"RRP": 49.95,
"PriceType": 1,
"PromoID": 194814003
}
进入这样的插入语句(假设我在其他地方准备好了 table 变量)
INSERT INTO <TABLE> (TRS_KEY,TRS_PTR,TailFlags,RRP,PriceType,PromoId) VALUES(712134,16974... and so on
我到了下面,但是完全搞砸了。我显然离这里很远。
foreach (dynamic d in r.Data)
{
try
{
context.Logger.LogLine($"Original dynamic object serialised to JSON -> {JsonConvert.SerializeObject(d)}");
JObject o = JObject.Parse(JsonConvert.SerializeObject(d));
var result = o.Descendants()
.OfType<JProperty>()
.Select(p => new KeyValuePair<string, object>(p.Path,
p.Value.Type == JTokenType.Array || p.Value.Type == JTokenType.Object
? null : p.Value));
var columns = result.Select(pairs => result.Select(pair => pair.Key).ToArray().ToString());
context.Logger.LogLine($"COLUMNS {JsonConvert.SerializeObject(columns)}");
var values = result.Select(pairs => result.Select(pair => pair.Value).ToArray());
context.Logger.LogLine($"VALUES TO GO INTO INSERTS {JsonConvert.SerializeObject(values)}");
var queryResult = db.Query(r.TableRef).Insert(columns, values);
db.Logger = compiled => {
context.Logger.Log($"{compiled.ToString()}");
};
}
catch (Exception ex)
{
context.Logger.LogLine($"{ex.ToString()}");
}
}
下面乱七八糟的产品有哪些:/
我通常不会诉诸 SO 的 'emotional' 方面,但如果有人能提供帮助并在此刻保留判断力,我将不胜感激。我只有这个周末才能提出这个概念,运行,我想我开始觉得我无法摆脱自己的头脑足够长的时间来简单而干净地解决这个问题。
编辑 - 尝试了下面的答案,但现在遇到了这个问题:
foreach (dynamic d in r.Data)
{
//context.Logger.LogLine($"{d.GetType()}");
try
{
context.Logger.LogLine($"{r.TableRef} {JsonConvert.SerializeObject(d)}");
JObject o = d;
var result = o.Descendants()
.OfType<JProperty>()
.Select(p => new KeyValuePair<string, object>(p.Path,
p.Value.Type == JTokenType.Array || p.Value.Type == JTokenType.Object
? null : p.Value));
IEnumerable<string> columns = result.Select(p => p.Key);
IEnumerable<object> values = result.Select(p => p.Value);
var queryResult = db.Query(r.TableRef).Insert(columns, values);
错误:(插入(列,值)中值下方的红色波浪线)
Severity Code Description Project File Line Suppression State
Error CS1503 Argument 3: cannot convert from 'System.Collections.Generic.IEnumerable<object>' to 'System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<object>>' S2CProcessDataStateMachine C:\Users\jmatson\source\repos\S2CProcessDataStateMachine\S2CProcessDataStateMachine\StepFunctionTasks.cs 113 Active
编辑:
改为
JObject o = d;
var result = o.Descendants()
.OfType<JProperty>()
.Select(p => new KeyValuePair<string, object>(p.Path,
p.Value.Type == JTokenType.Array || p.Value.Type == JTokenType.Object
? null : p.Value));
IEnumerable<string> columns = result.Select(p => p.Key);
IEnumerable<object> values = result.Select(p => p.Value);
// Add custom columns
IEnumerable<string> colAdded = columns.Add("STORE_ID").Add("last_modified");
IEnumerable<object> valAdded = values.Add(state.StoreId).Add(DateTime.Now);
var queryResult = db.Query(r.TableRef).AsInsert(colAdded, valAdded );
queryResult.Get();
在尝试 SQL 插入之前,这不会导致错误。正如您在上面看到的,我在插入之前添加了几个额外的列和值。所有列都在插入语句中正常显示,但请注意只有我手动添加的两个值出现了吗?其他都是空的? :(
INSERT INTO [TLog010000ItemSale] ([TRS_KEY], [TRS_PTR], [PLUID],
[Ext11], [Subtract], [Cancel], [Negative], [FuelItemCancel],
[StaffDiscAllow], [PriceOveride], [OnSale], [WSPriceOverride],
[ManPrice], [ManPriceAllw], [NoManWgnt], [WgtItem], [DecItem],
[Gallons], [ChainPrv], [NonMerch], [StoreCpn], [VendorCpn], [DiscAlw],
[Scan], [ReadSrv], [NextInfo], [ReplUnknown], [GSTExclFollow],
[PriceGrid], [DepID], [MSU], [RetnID], [TaxF], [QTY], [Price],
[Amount], [ExclPrice], [ExclAmount], [CaseQty], [TailFlags],
[NoStockDeduct], [NoLoyaltyPoints], [STORE_ID], [last_modified])
VALUES (, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
, , , , , , , , , , , 'A854', '2019-08-03 12:11:10')
鉴于 result
是 IEnumerable<KeyValuePair<string,object>>
类型,获取列和值列表的 linq 是一个简单的 linq Select
。 KeyValuePair
的键中可能有空值,因此请先删除它们:
result = result.Where(x => x.Key != null);
IEnumerable<string> columns = result.Select(p => p.Key);
IEnumerable<object> values = result.Select(p => p.Value);
在这种情况下,使用 var
与其说是帮助,不如说是阻碍。如果 columns
和 values
已声明为它们预期的类型,编译器将立即显示它是否与 linq 查询生成的任何内容匹配。
SqlKata 函数 Insert
用于多次插入,因此需要一组插入值列表:
var queryResult = db.Query(r.TableRef).Insert(columns, new[]{values});
请耐心等待,我已经工作了几个小时,感觉自己开始感到疲倦,犯了错误,并且看不到我应该看到的东西。如果这是一个愚蠢的问题,我深表歉意。我有一个动态对象循环。这些动态对象可以具有不同的形状,并且最终将被插入到与动态对象属性的列名称相匹配的数据库 table 中。因此,如果对象具有 'Title=Mr',则数据库中将有一个名为 'Title' 的数据库列。
我有下面的循环,我试图以某种方式将我的动态对象转换成一个列名数组和一个值数组,然后以某种方式在我的 Insert 语句中使用它们到 SQL 服务器使用 SqlKata (我愿意接受普通旧 ADO.NET 中的解决方案)。
然而,它严重损坏,我认为压力让我看不到像这样转动动态对象的更简单的解决方案:
{
"TRS_KEY": 712134,
"TRS_PTR": 16974,
"TailFlags": 0,
"RRP": 49.95,
"PriceType": 1,
"PromoID": 194814003
}
进入这样的插入语句(假设我在其他地方准备好了 table 变量)
INSERT INTO <TABLE> (TRS_KEY,TRS_PTR,TailFlags,RRP,PriceType,PromoId) VALUES(712134,16974... and so on
我到了下面,但是完全搞砸了。我显然离这里很远。
foreach (dynamic d in r.Data)
{
try
{
context.Logger.LogLine($"Original dynamic object serialised to JSON -> {JsonConvert.SerializeObject(d)}");
JObject o = JObject.Parse(JsonConvert.SerializeObject(d));
var result = o.Descendants()
.OfType<JProperty>()
.Select(p => new KeyValuePair<string, object>(p.Path,
p.Value.Type == JTokenType.Array || p.Value.Type == JTokenType.Object
? null : p.Value));
var columns = result.Select(pairs => result.Select(pair => pair.Key).ToArray().ToString());
context.Logger.LogLine($"COLUMNS {JsonConvert.SerializeObject(columns)}");
var values = result.Select(pairs => result.Select(pair => pair.Value).ToArray());
context.Logger.LogLine($"VALUES TO GO INTO INSERTS {JsonConvert.SerializeObject(values)}");
var queryResult = db.Query(r.TableRef).Insert(columns, values);
db.Logger = compiled => {
context.Logger.Log($"{compiled.ToString()}");
};
}
catch (Exception ex)
{
context.Logger.LogLine($"{ex.ToString()}");
}
}
下面乱七八糟的产品有哪些:/
我通常不会诉诸 SO 的 'emotional' 方面,但如果有人能提供帮助并在此刻保留判断力,我将不胜感激。我只有这个周末才能提出这个概念,运行,我想我开始觉得我无法摆脱自己的头脑足够长的时间来简单而干净地解决这个问题。
编辑 - 尝试了下面的答案,但现在遇到了这个问题:
foreach (dynamic d in r.Data)
{
//context.Logger.LogLine($"{d.GetType()}");
try
{
context.Logger.LogLine($"{r.TableRef} {JsonConvert.SerializeObject(d)}");
JObject o = d;
var result = o.Descendants()
.OfType<JProperty>()
.Select(p => new KeyValuePair<string, object>(p.Path,
p.Value.Type == JTokenType.Array || p.Value.Type == JTokenType.Object
? null : p.Value));
IEnumerable<string> columns = result.Select(p => p.Key);
IEnumerable<object> values = result.Select(p => p.Value);
var queryResult = db.Query(r.TableRef).Insert(columns, values);
错误:(插入(列,值)中值下方的红色波浪线)
Severity Code Description Project File Line Suppression State
Error CS1503 Argument 3: cannot convert from 'System.Collections.Generic.IEnumerable<object>' to 'System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<object>>' S2CProcessDataStateMachine C:\Users\jmatson\source\repos\S2CProcessDataStateMachine\S2CProcessDataStateMachine\StepFunctionTasks.cs 113 Active
编辑:
改为
JObject o = d;
var result = o.Descendants()
.OfType<JProperty>()
.Select(p => new KeyValuePair<string, object>(p.Path,
p.Value.Type == JTokenType.Array || p.Value.Type == JTokenType.Object
? null : p.Value));
IEnumerable<string> columns = result.Select(p => p.Key);
IEnumerable<object> values = result.Select(p => p.Value);
// Add custom columns
IEnumerable<string> colAdded = columns.Add("STORE_ID").Add("last_modified");
IEnumerable<object> valAdded = values.Add(state.StoreId).Add(DateTime.Now);
var queryResult = db.Query(r.TableRef).AsInsert(colAdded, valAdded );
queryResult.Get();
在尝试 SQL 插入之前,这不会导致错误。正如您在上面看到的,我在插入之前添加了几个额外的列和值。所有列都在插入语句中正常显示,但请注意只有我手动添加的两个值出现了吗?其他都是空的? :(
INSERT INTO [TLog010000ItemSale] ([TRS_KEY], [TRS_PTR], [PLUID], [Ext11], [Subtract], [Cancel], [Negative], [FuelItemCancel], [StaffDiscAllow], [PriceOveride], [OnSale], [WSPriceOverride], [ManPrice], [ManPriceAllw], [NoManWgnt], [WgtItem], [DecItem], [Gallons], [ChainPrv], [NonMerch], [StoreCpn], [VendorCpn], [DiscAlw], [Scan], [ReadSrv], [NextInfo], [ReplUnknown], [GSTExclFollow], [PriceGrid], [DepID], [MSU], [RetnID], [TaxF], [QTY], [Price], [Amount], [ExclPrice], [ExclAmount], [CaseQty], [TailFlags], [NoStockDeduct], [NoLoyaltyPoints], [STORE_ID], [last_modified]) VALUES (, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , 'A854', '2019-08-03 12:11:10')
鉴于 result
是 IEnumerable<KeyValuePair<string,object>>
类型,获取列和值列表的 linq 是一个简单的 linq Select
。 KeyValuePair
的键中可能有空值,因此请先删除它们:
result = result.Where(x => x.Key != null);
IEnumerable<string> columns = result.Select(p => p.Key);
IEnumerable<object> values = result.Select(p => p.Value);
在这种情况下,使用 var
与其说是帮助,不如说是阻碍。如果 columns
和 values
已声明为它们预期的类型,编译器将立即显示它是否与 linq 查询生成的任何内容匹配。
SqlKata 函数 Insert
用于多次插入,因此需要一组插入值列表:
var queryResult = db.Query(r.TableRef).Insert(columns, new[]{values});