Это невозможно. На данный момент (Spark 1.6.0 / 2.2.0 SNAPSHOT) Spark DataFrameWriter
поддерживает только четыре режима записи:
blockquote>
SaveMode.Overwrite
: перезаписать существующие данные.SaveMode.Append
: добавьте данные.SaveMode.Ignore
: проигнорируйте операцию (т. е. нет-op).SaveMode.ErrorIfExists
: параметр по умолчанию, выдайте исключение в runtime.Вы можете вставить вручную, например, с помощью
mapPartitions
(так как вы хотите, чтобы операция UPSERT была идемпотентной и как такая простая в использовании), напишите во временную таблицу и выполнить перезагрузку вручную или использовать триггеры.В целом достижение поведения при перезагрузке для пакетных операций и поддержание достойной производительности далеко не тривиально. Вы должны помнить, что в общем случае будет выполняться несколько параллельных транзакций (по одному на каждый раздел), поэтому вы должны убедиться, что конфликты записи не будут (как правило, с использованием конкретного раздела) или предоставить соответствующие процедуры восстановления. На практике может быть лучше выполнить и пакетную запись во временную таблицу и разрешить часть upsert непосредственно в базе данных.
public static KeyValuePair<object, object > Cast<K, V>(this KeyValuePair<K, V> kvp)
{
return new KeyValuePair<object, object>(kvp.Key, kvp.Value);
}
public static KeyValuePair<T, V> CastFrom<T, V>(Object obj)
{
return (KeyValuePair<T, V>) obj;
}
public static KeyValuePair<object , object > CastFrom(Object obj)
{
var type = obj.GetType();
if (type.IsGenericType)
{
if (type == typeof (KeyValuePair<,>))
{
var key = type.GetProperty("Key");
var value = type.GetProperty("Value");
var keyObj = key.GetValue(obj, null);
var valueObj = value.GetValue(obj, null);
return new KeyValuePair<object, object>(keyObj, valueObj);
}
}
throw new ArgumentException(" ### -> public static KeyValuePair<object , object > CastFrom(Object obj) : Error : obj argument must be KeyValuePair<,>");
}
Из ОП:
Вместо того, чтобы конвертировать весь мой словарь, я решил сохранить динамику моего объекта все время. Когда я позже получаю доступ к ключам и значениям моего словаря с помощью foreach, я использую foreach (динамический ключ в obj.Keys) и просто преобразую ключи и значения в строки.
Приведенные выше ответы все круто. Мне было легко сериализовать объект и десериализовать его как словарь.
var json = JsonConvert.SerializeObject(obj);
var dictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
Я не знаю, как это влияет на производительность, но это гораздо легче читать. Вы также можете обернуть его внутри функции.
public static Dictionary<string, TValue> ToDictionary<TValue>(object obj)
{
var json = JsonConvert.SerializeObject(obj);
var dictionary = JsonConvert.DeserializeObject<Dictionary<string, TValue>>(json);
return dictionary;
}
Используйте вот так:
var obj = new { foo = 12345, boo = true };
var dictionary = ToDictionary<string>(obj);
это должно работать:
для чисел, строк, даты и т. Д. :
public static void MyMethod(object obj)
{
if (typeof(IDictionary).IsAssignableFrom(obj.GetType()))
{
IDictionary idict = (IDictionary)obj;
Dictionary<string, string> newDict = new Dictionary<string, string>();
foreach (object key in idict.Keys)
{
newDict.Add(key.ToString(), idict[key].ToString());
}
}
else
{
// My object is not a dictionary
}
}
, если ваш словарь также содержит некоторые другие объекты:
public static void MyMethod(object obj)
{
if (typeof(IDictionary).IsAssignableFrom(obj.GetType()))
{
IDictionary idict = (IDictionary)obj;
Dictionary<string, string> newDict = new Dictionary<string, string>();
foreach (object key in idict.Keys)
{
newDict.Add(objToString(key), objToString(idict[key]));
}
}
else
{
// My object is not a dictionary
}
}
private static string objToString(object obj)
{
string str = "";
if (obj.GetType().FullName == "System.String")
{
str = (string)obj;
}
else if (obj.GetType().FullName == "test.Testclass")
{
TestClass c = (TestClass)obj;
str = c.Info;
}
return str;
}
Предполагая, что ключ может быть только строкой, но значение может быть чем угодно, попробуйте это
public static Dictionary<TKey, TValue> MyMethod<TKey, TValue>(object obj)
{
if (obj is Dictionary<TKey, TValue> stringDictionary)
{
return stringDictionary;
}
if (obj is IDictionary baseDictionary)
{
var dictionary = new Dictionary<TKey, TValue>();
foreach (DictionaryEntry keyValue in baseDictionary)
{
if (!(keyValue.Value is TValue))
{
// value is not TKey. perhaps throw an exception
return null;
}
if (!(keyValue.Key is TKey))
{
// value is not TValue. perhaps throw an exception
return null;
}
dictionary.Add((TKey)keyValue.Key, (TValue)keyValue.Value);
}
return dictionary;
}
// object is not a dictionary. perhaps throw an exception
return null;
}
Этот код безопасно работает для преобразования объекта в словарь (исходя из того, что исходный объект происходит из словаря):
private static Dictionary<TKey, TValue> ObjectToDictionary<TKey, TValue>(object source)
{
Dictionary<TKey, TValue> result = new Dictionary<TKey, TValue>();
TKey[] keys = { };
TValue[] values = { };
bool outLoopingKeys = false, outLoopingValues = false;
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source))
{
object value = property.GetValue(source);
if (value is Dictionary<TKey, TValue>.KeyCollection)
{
keys = ((Dictionary<TKey, TValue>.KeyCollection)value).ToArray();
outLoopingKeys = true;
}
if (value is Dictionary<TKey, TValue>.ValueCollection)
{
values = ((Dictionary<TKey, TValue>.ValueCollection)value).ToArray();
outLoopingValues = true;
}
if(outLoopingKeys & outLoopingValues)
{
break;
}
}
for (int i = 0; i < keys.Length; i++)
{
result.Add(keys[i], values[i]);
}
return result;
}
Я использую этого помощника:
public static class ObjectToDictionaryHelper
{
public static IDictionary<string, object> ToDictionary(this object source)
{
return source.ToDictionary<object>();
}
public static IDictionary<string, T> ToDictionary<T>(this object source)
{
if (source == null)
ThrowExceptionWhenSourceArgumentIsNull();
var dictionary = new Dictionary<string, T>();
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source))
AddPropertyToDictionary<T>(property, source, dictionary);
return dictionary;
}
private static void AddPropertyToDictionary<T>(PropertyDescriptor property, object source, Dictionary<string, T> dictionary)
{
object value = property.GetValue(source);
if (IsOfType<T>(value))
dictionary.Add(property.Name, (T)value);
}
private static bool IsOfType<T>(object value)
{
return value is T;
}
private static void ThrowExceptionWhenSourceArgumentIsNull()
{
throw new ArgumentNullException("source", "Unable to convert object to a dictionary. The source object is null.");
}
}
используется только для вызова .ToDictionary()
объекта
Надеюсь, это поможет.
public static void MyMethod(object obj){
Dictionary<string, string> dicEditdata = data as Dictionary<string, string>;
string abc=dicEditdata["id"].ToString();}
предположим --- если вы поместите курсор на объект (obj) во время отладки, и если вы получите объект со значением {['id':'ID1003']}
, то вы можете использовать значение как
string abc=dicEditdata["id"].ToString();
Вы можете создать универсальный метод расширения, а затем использовать его для объекта, например:
public static class Extensions
{
public static KeyValuePair<TKey, TValue> ToKeyValuePair<TKey, TValue>(this Object obj)
{
// if obj is null throws exception
Contract.Requires(obj != null);
// gets the type of the obj parameter
var type = obj.GetType();
// checks if obj is of type KeyValuePair
if (type.IsGenericType && type == typeof(KeyValuePair<TKey, TValue>))
{
return new KeyValuePair<TKey, TValue>(
(TKey)type.GetProperty("Key").GetValue(obj, null),
(TValue)type.GetProperty("Value").GetValue(obj, null)
);
}
// if obj type does not match KeyValuePair throw exception
throw new ArgumentException($"obj argument must be of type KeyValuePair<{typeof(TKey).FullName},{typeof(TValue).FullName}>");
}
, и использование будет выглядеть так:
KeyValuePair<string,long> kvp = obj.ToKeyValuePair<string,long>();
Я использую этот простой метод:
public Dictionary<string, string> objToDict(XYZ.ObjectCollection objs) {
var dict = new Dictionary<string, string>();
foreach (KeyValuePair<string, string> each in objs){
dict.Add(each.Key, each.Value);
}
return dict;
}
Насколько я понимаю, вы не знаете, что такое ключи и значения, но хотите преобразовать их в строки?
Может быть, это может сработать:
public static void MyMethod(object obj)
{
var iDict = obj as IDictionary;
if (iDict != null)
{
var dictStrStr = iDict.Cast<DictionaryEntry>()
.ToDictionary(de => de.Key.ToString(), de => de.Value.ToString());
// use your dictStrStr
}
else
{
// My object is not an IDictionary
}
}
object parsedData = se.Deserialize(reader);
System.Collections.IEnumerable stksEnum = parsedData as System.Collections.IEnumerable;
тогда сможете его перечислить!
Простой способ:
public IDictionary<T, V> toDictionary<T, V>(Object objAttached)
{
var dicCurrent = new Dictionary<T, V>();
foreach (DictionaryEntry dicData in (objAttached as IDictionary))
{
dicCurrent.Add((T)dicData.Key, (V)dicData.Value);
}
return dicCurrent;
}