#c# #oracle
Вопрос:
Я пишу клиент API из спецификации, предоставленной Nswag studio. Я могу получить эти данные, используя предоставленные client.PlansAsync(apikey).GetAwaiter().GetResult()
, но я изо всех сил пытаюсь превратить возвращенную ICollection во что-то, что я могу массово вставить в таблицу базы данных Oracle.
Я попытался создать DataTable
, но во время преобразования в DataTable генерируется исключение. Я подозреваю, что это как-то связано с обнуляемыми типами в коллекции.
Я предполагаю, что я должен пытаться выполнять вставки с использованием Entity Framework, но, похоже, добавление всех дополнительных компонентов ядра EF является излишним для этого конкретного клиента.
Я чувствую, что методы массового копирования Oracle идеально подходят для того, что я намереваюсь, но я столкнулся с проблемой, указанной выше.
Буду признателен за любую помощь.
TIA
РЕДАКТИРОВАТЬ: вот код, о котором идет речь.
//first in the calling class
ICollection<Plans> plansFromApi = client_.PlansAsync(apiKey).GetAwaiter().GetResult();
ListToDatTable listToDt = new();
List<Plans> ps = plansFromApi.ToList();
DataTable dt = listToDt.ToDataTable<Plans>(ps);
//second the List to Datatable class
public class ListToDataTable
{
public DataTable ToDataTable<T>(List<T> items)
{
DataTable dataTable = new(typeof(T).Name);
PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach(T item in items)
{
var values = new object[Props.Length];
for(int i = 0; i < Props.Length; i )
{
values[i] = Props[i].GetValue(item);
}
//line where the exception is thrown
//System.ArgumentException: 'Input array is longer than the number of columns in this table.'
dataTable.Rows.Add(values);
}
}
}
РЕДАКТИРОВАТЬ 2:
Вот что получилось из студии Nswag. Это всего лишь один из 15 наборов данных, которые мне нужно получить. Это не тот, который я сейчас тестирую, поскольку у него 25 свойств, поэтому для краткости я включил одно из меньших. В конце все они будут одинаковыми, поскольку все они будут обрабатываться точно так же, и да, я также тестировал с этим набором данных и получил то же исключение.
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.5.2.0 (Newtonsoft.Json v12.0.0.0)")]
public partial class ContactGroupedManufacturer
{
[Newtonsoft.Json.JsonProperty("lastContacted", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public System.DateTimeOffset? LastContacted { get; set; }
[Newtonsoft.Json.JsonProperty("vendorContactId", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public int VendorContactId { get; set; }
[Newtonsoft.Json.JsonProperty("ManufacturerId", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public int ManufacturerId { get; set; }
[Newtonsoft.Json.JsonProperty("website", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public string Website { get; set; }
}
Здесь несколько строк данных:
Последний контакт | vendorContactId | Идентификатор производителя | Веб-сайт |
---|---|---|---|
6575 | 1848 | ||
6599 | 2693 | ||
6604 | 8878 | 06/08/2018 | |
6692 | 6879 | ||
6930 | 4040 | некоторый URL |
ОБНОВЛЕНИЕ 2021/11/10: я нашел пакет NuGet с именем MoreLINQ, который содержал метод расширения, который обрабатывал преобразование в a DataTable
.
ICollection<ActionPlans> actionPlans = client.ActionPlansAsync(apiKey).GetAwaiter().GetResult();
_logger.LogInformation(${actionPlans.Count} APs returned");
DataTable actionPlansDt = actionPlans.ToDataTable();
Комментарии:
1. Итак, где же код, который не работает, включая исключение? Предположим, я оставил свои догадки — брюки в прачечной.
2. @Marco У меня был момент вчера, когда я опубликовал это, но я добавил его.
3. У всех нас это бывает время от времени. Теперь, пожалуйста, добавьте упомянутое исключение и где оно встречается. Бонусные баллы, если вы можете предоставить схему таблицы и одну или две строки данных для воспроизведения.
4. Исключение происходит в инструкции
dataTable.Rows.Add(values)
5. Данное исключение достаточно ясно, у вас недостаточно столбцов в вашей таблице данных. Проверьте, сколько столбцов у вас есть, и сколько свойств вы пытаетесь поместить в эту таблицу. Вы также можете попытаться самостоятельно управлять процессом создания столбцов в DataTable из свойств, чтобы вы были уверены, какие свойства вы хотите обрабатывать.
Ответ №1:
Вы можете обернуть IEnumerable в IDataReader для перехода к методу BulkCopy. См., например: ObjectDataReader
Как только у вас будет IDataReader, передайте его для OracleBulkCopy.WriteToServer(IDataReader)
просмотра OracleBulkCopy.
Комментарии:
1. Будет ли это работать с Oracle? Глядя на код в репозитории, он, похоже, предназначен для SQL Server.
2. Да, OracleBulkCopy работает так же, как SqlBulkCopy. Смотрите Обновленный ответ.
Ответ №2:
Вероятно, у вас проблема с количеством столбцов в таблице данных. Попробуйте этот код:
public class ListToDataTable
{
public DataTable ToDataTable<T>(List<T> items)
{
DataTable dataTable = new DataTable();
PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
bool columnsAlreadyCreated=false;
foreach(T item in items)
{
if (columnsAlreadyCreated==false)
{
for(int i = 0; i < Props.Length; i )
{
dataTable.Columns.Add(Props[i].Name,Nullable.GetUnderlyingType(
Props[i].PropertyType) ?? Props[i].PropertyType);
}
columnsAlreadyCreated=true;
}
var values = new object[Props.Length];
for(int i = 0; i < Props.Length; i )
{
values[i] = Props[i].GetValue(item);
}
//line where the exception is thrown
//System.ArgumentException: 'Input array is longer than the number of columns in this table.'
dataTable.Rows.Add(values);
}
}
}
Комментарии:
1. Я попытался изменить код, но я все еще сталкиваюсь с проблемой с
nullable
типом. Когда я добираюсь до свойства, которое имеетSystem.Nullable...
, я получаю исключениеDataset does not support System.Nullable
2. @RobM хорошо, это другой тип исключения. Я изменил свой код, изменил полосу, которая добавляла столбцы в источник данных:
dataTable.Columns.Add(Props[i].Name,Nullable.GetUnderlyingType( Props[i].PropertyType) ?? Props[i].PropertyType);
Вы должны попробовать это сейчас.3. @RobM у тебя это работает?
4. Я закончил поиск пакета NuGet с именем morelinq, который имел метод расширения, который создавал базу данных на основе
ICollection
.