I'm having a bit of a problem with converting an empty (value is "NULL") Key field to a byte array with CsvHelper, i keep getting this exception:
CsvHelper.ReaderException: An unexpected error occurred.
---> System.FormatException: Could not find any recognizable digits.
at System.ParseNumbers.StringToInt(ReadOnlySpan`1 s, Int32 radix, Int32 flags, Int32& currPos)
at System.Convert.ToByte(String value, Int32 fromBase)
at CsvHelper.TypeConversion.ByteArrayConverter.HexStringToByteArray(String hex)
at CsvHelper.TypeConversion.ByteArrayConverter.ConvertFromString(String text, IReaderRow row, MemberMapData memberMapData)
at lambda_method(Closure )
at CsvHelper.Expressions.RecordCreator.Create[T]()
at CsvHelper.Expressions.RecordManager.Create[T]()
at CsvHelper.CsvReader.GetRecord[T]()
--- End of inner exception stack trace ---
The mapping is set up like this:
public sealed class ZaznamMapping : ClassMap<Zaznam>
{
public ZaznamMapping(FileSettings configuration)
{
var nullValues = new[] { "NULL", "null", string.Empty };
for (int i = 0; i < configuration.Count(); i++)
{
switch (configuration[i])
{
case Col.Ignore: continue;
case Col.Id: Map(m => m.Id).Index(i).TypeConverterOption.NullValues(nullValues); break;
case Col.Idd: Map(m => m.Idd).Index(i).TypeConverterOption.NullValues(nullValues); break;
case Col.Data: Map(m => m.Data).Index(i).TypeConverterOption.NullValues(nullValues); break;
case Col.Key: Map(m => m.Key).Index(i).TypeConverterOption.NullValues(nullValues); break;
default: throw new NotSupportedException($"Mapping() - Unknown column \"{configuration[i].ToString()}\"!");
}
}
}
}
And Zaznam class:
public sealed class Zaznam
{
public int Id { get; set; }
public int Idd { get; set; }
public byte[] Data { get; set; }
public byte[] Key { get; set; }
}
The value in file Key coluimn is literally NULL (as in string containing the letters "NULL"). Should not the ByteArrayconverter respect the TypeConverterOptions?
The questions being:
Am I doing something wrong?
Should I be making my own converter instead?
It looks like the null value logic wasn't added to ByteArrayConverter. If you look at StringConverter, the same null logic is not in the ConvertFromString method for ByteArrayConverter. You should be able to create your own custom TypeConverter to add the logic and then register it for all byte[].
public class NullByteArrayConverter : ByteArrayConverter
{
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
{
foreach (var nullValue in memberMapData.TypeConverterOptions.NullValues)
{
if (text == nullValue)
{
return null;
}
}
return base.ConvertFromString(text, row, memberMapData);
}
}
csv.Configuration.TypeConverterCache.AddConverter<byte[]>(new NullByteArrayConverter());
Related
I need to convert a double field into a custom string output depending on a mapped class' parameter. This is most easily shown with code.
public enum Type {
Mod,
NonMod
}
public class Document {
public double Value { get; set; }
public Type DocType { get; set; }
}
Now attempting to convert the Value field...
public class DocumentMap : ClassMap<Document>
{
public DocumentMap
{
Map(m => m.Value).Index(0).Name("Value").TypeConverter<CustomDoubleConverter>()
Map(m => m.Type).Index(1).Name("Type");
}
private class CustomDoubleConverter : DefaultTypeConverter
{
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
{
return text == "ModVal" ? null : double.Parse(text);
}
public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
{
return (double)value == 0 /* && Document.Type == Type.Mod*/ ? "ModVal" : value.ToString();
}
}
}
I would need the Document type within CustomDoubleConverter to write "ModVal" only for Mod type documents. The only issue is converting the value to a string as converting back would mean it was properly delineated initially. I would need to know the document types for each of the documents, so I don't believe a parameter could be passed into the DocumentMap instantiation as it is only instantiated once.
I'm not quite sure I understand all of your logic, but I think Convert could work for you in the ClassMap.
public class DocumentMap : ClassMap<Document>
{
public DocumentMap()
{
Map(m => m.Value).Name("Value")
.Convert(args =>
{
var value = args.Row.GetField<string>(0);
return value == "ModVal" ? 0 : double.Parse(value);
}).Convert(args =>
{
return args.Value.Value == 0 && args.Value.DocType == Type.Mod ? "ModVal" : args.Value.Value.ToString();
});
Map(m => m.DocType).Index(1).Name("Type");
}
}
I have a small, fixed number of enums in their own .cs file in my custom namespace. Most of the enum names is the prefix of the corresponding table name in my SQLite database. As such, the string and int values in each enum are the record values for name and id respectively, therefore allowing me to easily keep track of which data to pass in methods that perform an SQL query.
public enum TableNamePrefix //respective table name would be "TableNamePrefix_SomeNameHere"
{
value1 = 1, //name = "value1", id = 1
value2 = 2, //name = "value2", id = 2
//...
}
public enum TableNamePrefix2
{
//...
}
//...
The goal is to simplify my database search criteria whenever I do a query which would heavily limit the chance of receiving a null record. Here is one of the methods I use to return a table row.
public static T GetTableRow(DBTableNameAbberviations tableNameAbb, Enum prefix,
string keyword = "", string name = "") //tableNameAbb is another enum
The method above works as expected, but I don't want Enum prefix to allow any Enum to be passed in, which brings me to my question. Is there a way to constrain this to a single or multiple user defined enums? In other words, rather than pass in any generic enum to my second parameter, is there a way to limit it to TableNamePrefix and my other omitted enums? If not, then what could a workaround be?
I thought about using a generic method with constraints, but where T2: System.Enum would still allow any Enum to be used.
You may consider using a type safe enum, since it seems you have additional data you want to accompany your enum.
This is the base class we will use for our type safe enums. It provides the basics for all type safe enums, the value and the name.
public abstract class TypeSafeEnumBase<TValue>
{
public readonly TValue Value;
public readonly string Name;
protected TypeSafeEnumBase(TValue value, string name)
{
this.Value = value;
this.Name = name;
}
public override string ToString()
{
return Name;
}
private static TypeSafeEnumBase<TValue>[] Items { get; set; }
public static IEnumerable<TypeSafeEnumBase<TValue>> GetValues<TType>()
{
if (Items == null || Items.Length == 0)
{
Dictionary<string, TType> items = typeof(TType)
.GetFields(BindingFlags.Public | BindingFlags.Static)
.Where(f => f.FieldType == typeof(TType))
.ToDictionary(f => f.Name,
f => (TType)f.GetValue(null));
Items = items.Values.Cast<TypeSafeEnumBase<TValue>>().ToArray();
}
foreach (TypeSafeEnumBase<TValue> item in Items)
{
yield return item;
}
}
}
This is your 'table details' setup as a type safe enum. In this class we implement any additional properties that may be needed, e.g. Prefix, Keyword, etc.
public sealed class TableDetails : TypeSafeEnumBase<int>
{
public static TableDetails TableOneDetails = new TableDetails(1, "value1", "TableNamePrefix1","table1keyword");
public static TableDetails TableTwoDetails = new TableDetails(2, "value2","TableNamePrefix2", "table2keyword");
public static TableDetails TableThreeDetails = new TableDetails(3, "value3", "TableNamePrefix3", "table3keyword");
public TableDetails(int value, string name, string prefix, string keyword) : base(value, name)
{
Prefix = prefix;
Keyword = keyword;
}
public string Prefix { get; }
public string Keyword { get; }
public static bool TryParse(int value, out TableDetails tableDetails)
{
return TryParse(value.ToString(), out tableDetails);
}
public static bool TryParse(string value, out TableDetails tableDetails)
{
try
{
tableDetails= Parse(value);
return true;
}
catch
{
tableDetails= null;
return false;
}
}
public static TableDetails Parse(int value)
{
return Parse(value.ToString());
}
public static TableDetails Parse(string value)
{
switch (value)
{
case "1":
case nameof(TableOneDetails):
return TableOneDetails;
case "2":
case nameof(TableTwoDetails):
return TableTwoDetails;
case "3":
case nameof(TableThreeDetails):
return TableThreeDetails;
default:
throw new IndexOutOfRangeException($"{nameof(TableDetails)} doesn't contain {value}.");
}
}
public override string ToString()
{
return base.Name;
}
}
You can now change your GetTableRow method to accept the type TableDetails. In addition you only have one parameter to pass in, the TableDetails, and if you need to add more parameters you can update your TableDetails object without having to change your GetTableRow method signature.
public static T GetTableRow(TableDetails tableDetails)
Contrain a type is difficult (unless it is a generic type), what you could do is create a type parameter on the method to the enum and constrain it to the enum type:
... GetTableRow<TEnum>(... TEnum prefix, ...) : where TEnum : EnumType {}
, or just throw an exception if enum is not the type you want.
rI know two tools : Value injector and Automapper. Each of them is currently supporting one of the feature, that i realy need. :) Background: i'm using stored procedure to load data from DB. relations 1 to many are handled as XML properties. Let's consider following example
public class AutorDto
{
public string Name { get; set; }
public List<Post> Posts { get; set; }
public ICity City { get; set; }
}
public interface ICity
{
string Name { get; set; }
string Code { get; set; }
}
public class CityDto
{
public string Name { get; set; }
public string Code { get; set; }
}
public class PostDto
{
public DateTime Date { get; set; }
public string Content { get; set; }
}
I have stored procedure, that will return me this structure in following schema :
public class Autor_From_Stored_Procedure
{
public string Name { get; set; }
public string Posts { get; set; }
public string CityName { get; set; }
public string CityCode { get; set; }
}
In order to map Autor_From_Stored_Procedure to AutorDto we must handle two topics:
Deserializing from XML (i've managed to handle this problem using automapper. I've used this topic : Automapper to create object from XML) and this article : http://www.codeproject.com/Articles/706992/Using-AutoMapper-with-Complex-XML-Data
Unflattening. It seems, that AutoMapper is not supporting convention based unflattening. Is, that true ? I saw, that there is posibility to declare some string (e.g. "City") as Unflattened object and everything should work - but value injector offers this as a convetion based standard:
objectToIll.InjectFrom < UnflatLoopInjection>(object) - without neccessity to declare which properties [names in specific] would be deflattened) Is this also possible with automapper ?
If not, then maybe i should focus on value injector. If so - the problem from the 1) point is still valid (hopefully it is solved as easly as in automapper)
Penny for your thoughts!
##Update
I've changed Dto definitions adding interface to City (as this is my case)
I will post anwser to my question - maybe it will help someone. I've moved from Automapper to Valueinjecter. Xml binding was done using custom AddMap() and using XmlSerializer (no magic here)
But it turns out, that there will be problem with Interface on "Autor" class (and deflattening) You cannot simply create interface instance and this was the problem. I've modified slightly valueinjecter Tunnelier class to handle such case.
Firstly i've tried to cover this using somehow convention (if you find property ISomething, cut "I" add "Dto" But it is not elegant solution. So i ended up with custom : Inteface+Class mapping (so i'm pointing out : if you see ISomething interface, create instance of SomethingDto) Here is the modified code (maybe this could be added to valueinjecter implementation ?) The main "Mapper" class is not partial so i've defined new class for those mappings:
namespace Omu.ValueInjecter
{
public partial class MapperActivations
{
public static ConcurrentDictionary<Type, Type> InterfaceActivations = new ConcurrentDictionary<Type, Type>();
public static void AddInterfaceActivation<Interface, Class>()
{
InterfaceActivations.AddOrUpdate(typeof(Interface), typeof(Class), (key, oldValue) => typeof(Class));
}
}
}
Here are modified valueInjected classes:
public static class TunnelierCustom
{
public static PropertyWithComponent Digg(IList<string> trail, object o)
{
var type = o.GetType();
if (trail.Count == 1)
{
return new PropertyWithComponent { Component = o, Property = type.GetProperty(trail[0]) };
}
var prop = type.GetProperty(trail[0]);
var val = prop.GetValue(o);
if (val == null)
{
if (prop.PropertyType.IsInterface)
{
if (MapperActivations.InterfaceActivations.ContainsKey(prop.PropertyType))
{
val = Activator.CreateInstance(MapperActivations.InterfaceActivations[prop.PropertyType]);
}
else
{
throw new Exception("Unable to create instance of: " + prop.PropertyType.Name + ". Are you missing InterfaceActivations bidning? Please add it using MapperActivations.AddInterfaceActivation<Interface, Class>() statement");
}
}
else
{
val = Activator.CreateInstance(prop.PropertyType);
}
prop.SetValue(o, val);
}
trail.RemoveAt(0);
return Digg(trail, val);
}
public static PropertyWithComponent GetValue(IList<string> trail, object o, int level = 0)
{
var type = o.GetType();
if (trail.Count == 1)
{
return new PropertyWithComponent { Component = o, Property = type.GetProperty(trail[0]), Level = level };
}
var prop = type.GetProperty(trail[0]);
var val = prop.GetValue(o);
if (val == null) return null;
trail.RemoveAt(0);
return GetValue(trail, val, level + 1);
}
}
/// <summary>
/// performs flattening and unflattening
/// first version of this class was made by Vadim Plamadeala ☺
/// </summary>
public static class UberFlatterCustom
{
public static IEnumerable<PropertyWithComponent> Unflat(string flatPropertyName, object target, Func<string, PropertyInfo, bool> match, StringComparison comparison)
{
var trails = TrailFinder.GetTrails(flatPropertyName, target.GetType().GetProps(), match, comparison, false).Where(o => o != null);
return trails.Select(trail => TunnelierCustom.Digg(trail, target));
}
public static IEnumerable<PropertyWithComponent> Unflat(string flatPropertyName, object target, Func<string, PropertyInfo, bool> match)
{
return Unflat(flatPropertyName, target, match, StringComparison.Ordinal);
}
public static IEnumerable<PropertyWithComponent> Unflat(string flatPropertyName, object target)
{
return Unflat(flatPropertyName, target, (upn, pi) => upn == pi.Name);
}
public static IEnumerable<PropertyWithComponent> Flat(string flatPropertyName, object source, Func<string, PropertyInfo, bool> match)
{
return Flat(flatPropertyName, source, match, StringComparison.Ordinal);
}
public static IEnumerable<PropertyWithComponent> Flat(string flatPropertyName, object source, Func<string, PropertyInfo, bool> match, StringComparison comparison)
{
var trails = TrailFinder.GetTrails(flatPropertyName, source.GetType().GetProps(), match, comparison).Where(o => o != null);
return trails.Select(trail => TunnelierCustom.GetValue(trail, source));
}
public static IEnumerable<PropertyWithComponent> Flat(string flatPropertyName, object source)
{
return Flat(flatPropertyName, source, (up, pi) => up == pi.Name);
}
}
public class UnflatLoopCustomInjection : ValueInjection
{
protected override void Inject(object source, object target)
{
var sourceProps = source.GetType().GetProps();
foreach (var sp in sourceProps)
{
Execute(sp, source, target);
}
}
protected virtual bool Match(string upn, PropertyInfo prop, PropertyInfo sourceProp)
{
return prop.PropertyType == sourceProp.PropertyType && upn == prop.Name;
}
protected virtual void SetValue(object source, object target, PropertyInfo sp, PropertyInfo tp)
{
tp.SetValue(target, sp.GetValue(source));
}
protected virtual void Execute(PropertyInfo sp, object source, object target)
{
if (sp.CanRead)
{
var endpoints = UberFlatterCustom.Unflat(sp.Name, target, (upn, prop) => Match(upn, prop, sp)).ToArray();
foreach (var endpoint in endpoints)
{
SetValue(source, endpoint.Component, sp, endpoint.Property);
}
}
}
}
And this is example use :
MapperActivations.AddInterfaceActivation<ICity, City>();
Mapper.AddMap<Auto_From_Stored_Procedure, AutorDto>(src =>
{
var res = new User();
res.InjectFrom<UnflatLoopCustomInjection>(src);
res.Posts = Mapper.Map<XElement, List<Posts>>(src.PostsXml , "PostDto"); //this is mapping using XmlSerializer, PostsXml is XElement.Parse(Posts) in Autor_From_Stored_Procedure.
return res;
});
new version has been released 3.1
you can now specify an activator parameter for the UnflatLoopInjection
have a look at this unit test
I'm trying to import an Excel file in SSIS that has merged cells, and SSIS reads those merged cells as NULL other than the first cell which has the data.
I'm trying to parse the information and for that I want to apply the merged cell data to every cell that was merged previously.
I have this code that I found that applies the code to the F1 column (In my Input)
// This script adjusts the value of all string fields
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
string filledField1 = "";
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
// Check if the value is null
if (Row.F1_IsNull)
{
// If null => replace value by variable
Row.F1 = filledField1;
}
else
{
// If not null => replace variable by value
filledField1 = Row.F1;
}
}
}
What I want is to apply this code for multiple columns through a foreach loop, but I can only do it if I know the names of the columns previously.
How can I transform this code to apply the transformation for every row of every column instead of the F1 column only?
You're not going to be able to genercize it. If someone knows otherwise, I'll be happy to delete this and bounty their answer.
The Why it can't be done is that in your Input0_ProcessInputRow method, in ScriptMain class, accepts an Input0Buffer as the parameter. Input0Buffer is an autogenerated class. The following comment heads the BufferWrapper.cs file which defines the Input0Buffer class
/* THIS IS AUTO-GENERATED CODE THAT WILL BE OVERWRITTEN! DO NOT EDIT!
* Microsoft SQL Server Integration Services buffer wrappers
* This module defines classes for accessing data flow buffers
* THIS IS AUTO-GENERATED CODE THAT WILL BE OVERWRITTEN! DO NOT EDIT! */
So, that class is what defines the things available to you in your ProcessInputMethod. It generates a bunch of getters and/or setter methods plus an IsNull method for all the columns you select before you clicked the "Edit script" button.
Input0Buffer is derived from the ScriptBuffer class. ScriptBuffer has as its definition
namespace Microsoft.SqlServer.Dts.Pipeline
{
public class ScriptBuffer
{
protected PipelineBuffer Buffer;
protected int[] BufferColumnIndexes;
public ScriptBuffer(PipelineBuffer BufferToUse, int[] BufferColumnIndexesToUse, OutputNameMap OutputMap);
protected object this[int ColumnIndex] { get; set; }
protected void AddRow();
protected void DirectRow(string outputName);
protected bool EndOfRowset();
protected bool IsNull(int ColumnIndex);
protected bool NextRow();
protected void SetEndOfRowset();
protected void SetNull(int ColumnIndex);
}
}
What's important to note that the PipelineBuffer instance called Buffer, is defined as protected in the ScriptBuffer class. It is not defined as anything in our autogenerated class so it's not accessible outside that class definition. That means when we're using the instance, as we do inside our ScriptMain, we can't touch the protected members as they behave as if private.
I'm sure you could implement an IEnumerable something interface so you could do what you're wanting to do on the Input0Buffer class but know that every time you open the script up, Visual Studio is going to regenerate the class and obliterate your edits.
As I type this, I am making a note to check up on how Extension Methods as they might provide an approach...
As a matter of fact, you actually can access the underlying object in a script and iterate over a buffer, without using the named columns. You need to inherit the buffer and use this inherited class in public override void ProcessInput(int InputID, string InputName, PipelineBuffer Buffer, OutputNameMap OutputMap). I usually use a class inherited from Input0Buffer ( the autogenrated one) so I can access both the named and the iterateable columns.You can get the indexes to the columns by using Reflection
e.g.:
using System.Reflection;
...
#region Input0ByIndexBuffer
//inherit via BufferWrapper
public class Input0ByIndexBuffer : Input0Buffer
{
public Dictionary<string, int> ColumnIndexes = new Dictionary<string, int>();
public Input0ByIndexBuffer(PipelineBuffer Buffer, int[] BufferColumnIndexes, OutputNameMap OutputMap) : base(Buffer, BufferColumnIndexes, OutputMap)
{
IList<string> propertyList = new List<string>();
foreach (PropertyInfo property in typeof(Input0Buffer).GetProperties())
if (!property.Name.EndsWith("_IsNull"))
propertyList.Add(property.Name.ToUpperInvariant());
for (int i = 0; i < propertyList.Count; i++)
ColumnIndexes[propertyList[i]] = i;
}
new public bool IsNull(int columnIndex)
{
return base.IsNull(columnIndex);
}
new public void SetNull(int columnIndex)
{
base.SetNull(columnIndex);
}
new public object this[int ColumnIndex]
{
get
{
return base[ColumnIndex];
// return GetObject(ColumnIndex);
}
set
{
//SetObject(ColumnIndex, value, false);
base[ColumnIndex] = value;
}
}
public BufferColumn GetColumnInfo(int columnIndex)
{
return Buffer.GetColumnInfo(BufferColumnIndexes[columnIndex]);
}
//expose the Buffer.Get methods using the columnindex, this enables iterations over index instead of columns names
public object GetObject(int columnIndex)
{
BufferColumn columnInfo = GetColumnInfo(columnIndex);
switch (columnInfo.DataType)
{
case DataType.DT_BOOL:
case DataType.DT_BYREF_BOOL:
return GetBoolean(columnIndex);
case DataType.DT_I2:
case DataType.DT_BYREF_I2:
return GetInt16(columnIndex);
case DataType.DT_I4:
case DataType.DT_BYREF_I4:
return GetInt32(columnIndex);
case DataType.DT_R4:
case DataType.DT_BYREF_R4:
return GetSingle(columnIndex);
case DataType.DT_R8:
case DataType.DT_BYREF_R8:
return GetDouble(columnIndex);
case DataType.DT_CY:
case DataType.DT_BYREF_CY:
case DataType.DT_DECIMAL:
case DataType.DT_NUMERIC:
case DataType.DT_BYREF_DECIMAL:
case DataType.DT_BYREF_NUMERIC:
return GetDecimal(columnIndex);
case DataType.DT_I1:
case DataType.DT_BYREF_I1:
return GetSByte(columnIndex);
case DataType.DT_UI1:
case DataType.DT_BYREF_UI1:
return GetByte(columnIndex);
case DataType.DT_UI2:
case DataType.DT_BYREF_UI2:
return GetUInt16(columnIndex);
case DataType.DT_UI4:
case DataType.DT_BYREF_UI4:
return GetUInt32(columnIndex);
case DataType.DT_I8:
case DataType.DT_BYREF_I8:
return GetInt64(columnIndex);
case DataType.DT_UI8:
case DataType.DT_BYREF_UI8:
return GetUInt64(columnIndex);
case DataType.DT_DBDATE:
case DataType.DT_BYREF_DBDATE:
return GetDate(columnIndex);
case DataType.DT_DATE:
case DataType.DT_BYREF_DATE:
case DataType.DT_FILETIME:
case DataType.DT_BYREF_FILETIME:
case DataType.DT_DBTIME:
case DataType.DT_BYREF_DBTIME:
case DataType.DT_DBTIMESTAMP:
case DataType.DT_BYREF_DBTIMESTAMP:
case DataType.DT_DBTIME2:
case DataType.DT_BYREF_DBTIME2:
case DataType.DT_DBTIMESTAMPOFFSET:
case DataType.DT_BYREF_DBTIMESTAMPOFFSET:
case DataType.DT_DBTIMESTAMP2:
case DataType.DT_BYREF_DBTIMESTAMP2:
return GetDateTime(columnIndex);
default:
throw new Exception(columnInfo.DataType.ToString() + " not yet supported ");
}
}
public void SetObject(int columnIndex, object value, bool failSilently = true)
{
BufferColumn columnInfo = GetColumnInfo(columnIndex);
try
{
switch (columnInfo.DataType)
{
case DataType.DT_BOOL:
case DataType.DT_BYREF_BOOL:
SetBoolean(columnIndex, (bool)value);
break;
case DataType.DT_I2:
case DataType.DT_BYREF_I2:
SetInt16(columnIndex, (short)value);
break;
case DataType.DT_I4:
case DataType.DT_BYREF_I4:
SetInt32(columnIndex, (int)value);
break;
case DataType.DT_R4:
case DataType.DT_BYREF_R4:
SetSingle(columnIndex, (float)value);
break;
case DataType.DT_R8:
case DataType.DT_BYREF_R8:
SetDouble(columnIndex, (double)value);
break;
case DataType.DT_CY:
case DataType.DT_BYREF_CY:
case DataType.DT_DECIMAL:
case DataType.DT_NUMERIC:
case DataType.DT_BYREF_DECIMAL:
case DataType.DT_BYREF_NUMERIC:
SetDecimal(columnIndex, (decimal)value);
break;
case DataType.DT_I1:
case DataType.DT_BYREF_I1:
SetSByte(columnIndex, (sbyte)value);
break;
case DataType.DT_UI1:
case DataType.DT_BYREF_UI1:
SetByte(columnIndex, (byte)value);
break;
case DataType.DT_UI2:
case DataType.DT_BYREF_UI2:
SetUInt16(columnIndex, (ushort)value);
break;
case DataType.DT_UI4:
case DataType.DT_BYREF_UI4:
SetUInt32(columnIndex, (uint)value);
break;
case DataType.DT_I8:
case DataType.DT_BYREF_I8:
SetInt64(columnIndex, (long)value);
break;
case DataType.DT_UI8:
case DataType.DT_BYREF_UI8:
SetUInt64(columnIndex, (ulong)value);
break;
case DataType.DT_DBDATE:
case DataType.DT_BYREF_DBDATE:
SetDate(columnIndex, (DateTime)value);
break;
case DataType.DT_DATE:
case DataType.DT_BYREF_DATE:
case DataType.DT_FILETIME:
case DataType.DT_BYREF_FILETIME:
case DataType.DT_DBTIME:
case DataType.DT_BYREF_DBTIME:
case DataType.DT_DBTIMESTAMP:
case DataType.DT_BYREF_DBTIMESTAMP:
case DataType.DT_DBTIME2:
case DataType.DT_BYREF_DBTIME2:
case DataType.DT_DBTIMESTAMPOFFSET:
case DataType.DT_BYREF_DBTIMESTAMPOFFSET:
case DataType.DT_DBTIMESTAMP2:
case DataType.DT_BYREF_DBTIMESTAMP2:
SetDateTime(columnIndex, (DateTime)value);
break;
default:
throw new Exception(columnInfo.DataType.ToString() + " not yet supported ");
}
}
catch (Exception e)
{
if (failSilently == false)
throw e;
else
try { SetNull(columnIndex); } catch { }
}
}
public sbyte GetSByte(int columnIndex)
{
return Buffer.GetSByte(BufferColumnIndexes[columnIndex]);
}
public byte GetByte(int columnIndex)
{
return Buffer.GetByte(BufferColumnIndexes[columnIndex]);
}
public bool GetBoolean(int columnIndex)
{
return Buffer.GetBoolean(BufferColumnIndexes[columnIndex]);
}
public short GetInt16(int columnIndex)
{
return Buffer.GetInt16(BufferColumnIndexes[columnIndex]);
}
public ushort GetUInt16(int columnIndex)
{
return Buffer.GetUInt16(BufferColumnIndexes[columnIndex]);
}
public int GetInt32(int columnIndex)
{
return Buffer.GetInt32(BufferColumnIndexes[columnIndex]);
}
public uint GetUInt32(int columnIndex)
{
return Buffer.GetUInt32(BufferColumnIndexes[columnIndex]);
}
public long GetInt64(int columnIndex)
{
return Buffer.GetInt64(BufferColumnIndexes[columnIndex]);
}
public ulong GetUInt64(int columnIndex)
{
return Buffer.GetUInt64(BufferColumnIndexes[columnIndex]);
}
public decimal GetDecimal(int columnIndex)
{
return Buffer.GetDecimal(BufferColumnIndexes[columnIndex]);
}
public float GetSingle(int columnIndex)
{
return Buffer.GetSingle(BufferColumnIndexes[columnIndex]);
}
public double GetDouble(int columnIndex)
{
return Buffer.GetDouble(BufferColumnIndexes[columnIndex]);
}
public DateTime GetDateTime(int columnIndex)
{
return Buffer.GetDateTime(BufferColumnIndexes[columnIndex]);
}
public DateTime GetDate(int columnIndex)
{
return Buffer.GetDate(BufferColumnIndexes[columnIndex]);
}
public byte[] GetBytes(int columnIndex)
{
return Buffer.GetBytes(BufferColumnIndexes[columnIndex]);
}
public DateTimeOffset GetDateTimeOffset(int columnIndex)
{
return Buffer.GetDateTimeOffset(BufferColumnIndexes[columnIndex]);
}
public Guid GetGuid(int columnIndex)
{
return Buffer.GetGuid(BufferColumnIndexes[columnIndex]);
}
public string GetString(int columnIndex)
{
return Buffer.GetString(BufferColumnIndexes[columnIndex]);
}
public TimeSpan GetTime(int columnIndex)
{
return Buffer.GetTime(BufferColumnIndexes[columnIndex]);
}
//to test against componentwrapper?
public uint GetBlobLength(int columnIndex)
{
return Buffer.GetBlobLength(BufferColumnIndexes[columnIndex]);
}
public byte[] GetBlobData(int columnIndex, int offset, int count)
{
return Buffer.GetBlobData(BufferColumnIndexes[columnIndex], offset, count);
}
public void AddBlobData(int columnIndex, byte[] data)
{
Buffer.AddBlobData(BufferColumnIndexes[columnIndex], data);
}
public void AddBlobData(int columnIndex, byte[] data, int count)
{
Buffer.AddBlobData(BufferColumnIndexes[columnIndex], data, count);
}
public void ResetBlobData(int columnIndex)
{
Buffer.ResetBlobData(columnIndex);
}
public void SetBoolean(int columnIndex, bool value)
{
Buffer.SetBoolean(BufferColumnIndexes[columnIndex], value);
}
public void SetByte(int columnIndex, byte value)
{
Buffer.SetByte(BufferColumnIndexes[columnIndex], value);
}
public void SetBytes(int columnIndex, byte[] bytesValue)
{
Buffer.SetBytes(BufferColumnIndexes[columnIndex], bytesValue);
}
public void SetDate(int columnIndex, DateTime value)
{
Buffer.SetDate(BufferColumnIndexes[columnIndex], value);
}
public void SetDateTime(int columnIndex, DateTime value)
{
Buffer.SetDateTime(BufferColumnIndexes[columnIndex], value);
}
public void SetDateTimeOffset(int columnIndex, DateTimeOffset value)
{
Buffer.SetDateTimeOffset(BufferColumnIndexes[columnIndex], value);
}
public void SetDecimal(int columnIndex, decimal value)
{
Buffer.SetDecimal(BufferColumnIndexes[columnIndex], value);
}
public void SetDouble(int columnIndex, double value)
{
Buffer.SetDouble(BufferColumnIndexes[columnIndex], value);
}
public void SetGuid(int columnIndex, Guid value)
{
Buffer.SetGuid(BufferColumnIndexes[columnIndex], value);
}
public void SetInt16(int columnIndex, short value)
{
Buffer.SetInt16(BufferColumnIndexes[columnIndex], value);
}
public void SetInt32(int columnIndex, int value)
{
Buffer.SetInt32(BufferColumnIndexes[columnIndex], value);
}
public void SetInt64(int columnIndex, long value)
{
Buffer.SetInt64(BufferColumnIndexes[columnIndex], value);
}
public void SetSByte(int columnIndex, sbyte value)
{
Buffer.SetSByte(BufferColumnIndexes[columnIndex], value);
}
public void SetSingle(int columnIndex, float value)
{
Buffer.SetSingle(BufferColumnIndexes[columnIndex], value);
}
public void SetString(int columnIndex, string value)
{
Buffer.SetString(BufferColumnIndexes[columnIndex], value);
}
public void SetTime(int columnIndex, TimeSpan value)
{
Buffer.SetTime(BufferColumnIndexes[columnIndex], value);
}
public void SetUInt16(int columnIndex, ushort value)
{
Buffer.SetUInt16(BufferColumnIndexes[columnIndex], value);
}
public void SetUInt32(int columnIndex, uint value)
{
Buffer.SetUInt32(BufferColumnIndexes[columnIndex], value);
}
public void SetUInt64(int columnIndex, ulong value)
{
Buffer.SetUInt64(BufferColumnIndexes[columnIndex], value);
}
}
#endregion
and use it in:
public void Input0_ProcessInputRow(Input0ByIndexBuffer Row)
{
//do your code
}
public override void ProcessInput(int InputID, string InputName, PipelineBuffer Buffer, OutputNameMap OutputMap)
{
if (InputName.Equals(#"Input 0", StringComparison.Ordinal))
{
Input0_ProcessInput(new Input0ByIndexBuffer(Buffer, GetColumnIndexes(InputID), OutputMap));
}
}
public void Input0_ProcessInput(Input0ByIndexBuffer Buffer)
{
while (Buffer.NextRow())
{
Input0_ProcessInputRow(Buffer);
}
}
The actual indexes to the column names I'll get from the Dictionary ColumnIndexes
For a project i've created several struct in C#.
The probject itself is a ASP.Net MVC 2 project.
snip:
struct TDummy
{
private char _value;
public TDummy(char value)
{
this._value = value; // Restrictions
}
}
I created this because I needed to restrict a char-variable to a specific number of values. (I could have created an Enum, but these values are also used in the database, and then i would still need to convert them)
Now i need to create a JsonResult, like
return Json(new { Value = new TDummy('X') });
But when I do this, I get a result of:
{"Value":{}}
I expected to get a result of
{"Value":"X"}
I've tried several things, like TypeConverter (CanConvertTo(string)), Custom Type Serializer (JavaScriptSerializer.RegisterConverters()), but either they don't work or they must return a 'Complex' json-object.
{"Value":{"Name":"Value"}}
Any thoughts on this?
I want to serialize a value-type as a value...
If anyone is interested, i've create a small demo (console app) to illustrate this:
public struct TState
{
public static TState Active = new TState('A');
public static TState Pending = new TState('P');
private char _value;
public TState(char value)
{
switch (value)
{
case 'A':
case 'P':
this._value = value; // Known values
break;
default:
this._value = 'A'; // Default value
break;
}
}
public static implicit operator TState(char value)
{
switch (value)
{
case 'A':
return TState.Active;
case 'P':
return TState.Pending;
}
throw new InvalidCastException();
}
public static implicit operator char(TState value)
{
return value._value;
}
public override string ToString()
{
return this._value.ToString();
}
}
public class Test { public TState Value { get; set; } }
class Program
{
static void Main(string[] args)
{
Test o = new Test();
o.Value = 'P'; // From Char
char c = o.Value; // To Char
Console.WriteLine(o.Value); // Writes 'P'
Console.WriteLine(c); // Writes 'P'
JavaScriptSerializer jser = new JavaScriptSerializer();
Console.WriteLine(jser.Serialize(o)); // Writes '{"Value":{}}'
Console.ReadLine();
}
}