SQL CLR Function: int column preventing project form publishing - c#

I am getting
Parameter 'Volm' can be removed; its initial value is never used,
despite, as far as I can tell, the value being used.
I am getting
Unnecessary assignment of a value to 'Volm'
for that same value being assigned.
And, on publish, I am getting
Function signature of "FillRow" method does not match SQL declaration for table valued CLR function'GetQuoteHistory' due to column 7,
despite having 7 columns for each, and matching data types.
If I comment out the last column in the function, table definition, and assignment, the project publishes.
I am banging my head, and not because there is music playing. Appreciate other sets of eyes. The above messages are noted on the relevant lines.
public class TableFunctions
{
[SqlFunction(FillRowMethodName = "FillQuoteHistoryRow",
TableDefinition = "Symbol NVarChar(10), TradeTime datetime,
Opn money, High money,
Low money, Clos money,
Volm int")]
public static IEnumerable GetQuoteHistory(string Symbol)
{
return new QuoteHistory(Symbol);
}
private static void FillQuoteHistoryRow(Object Item, ref string Symbol, ref DateTime TradeTime,
ref decimal Opn, ref decimal High,
ref decimal Low, ref decimal Clos,
int Volm) // mouseover: Parameter 'Volm' can be removed; its initial value is never used.
// on publish, builds, but returns:
// (278,1): SQL72014: .Net SqlClient Data Provider: Msg 6258, Level 16, State 1, Procedure GetQuoteHistory,
// Line 1 Function signature of "FillRow" method(as designated by SqlFunctionAttribute.FillRowMethodName)
// does not match SQL declaration for table valued CLR function'GetQuoteHistory' due to column 7.
{
QuoteHistoryItem QHItem = (QuoteHistoryItem)Item;
Symbol = QHItem.Symbol;
TradeTime = QHItem.Time;
Opn = QHItem.Opn;
High = QHItem.High;
Low = QHItem.Low;
Clos = QHItem.Clos;
Volm = QHItem.Volm; // mouseover: Unnecessary assignment of a value to 'Volm'
} // method
} // class TableFunctions
public class QuoteHistory : List<QuoteHistoryItem>
{
public QuoteHistory(string Symbol)
{
LoadQuoteHistory(Symbol);
} // method QuoteHistory
public void LoadQuoteHistory(string Symbol)
{
string path = "C:\\Github\\Uranus\\SQLCLR\\APIOrig\\";
string func = "TIME_SERIES_INTRADAY_EXTENDED";
string interval = "1min";
string slice = "year1month1";
string apikey = "XBM9114REDBJXZIV";
string QueryURL = "https://www.alphavantage.co/query" +
"?function=" + func +
"&symbol=" + (string)Symbol +
"&interval=" + interval +
"&slice=" + slice +
"&apikey=" + apikey;
QueryURL = "file:///" + path + "Example.csv"; // FOR TESTING
Uri queryUri = new Uri(QueryURL);
using (WebClient client = new WebClient())
{
using (MemoryStream stream = new MemoryStream(client.DownloadDataTaskAsync(queryUri).Result))
{
stream.Position = 0;
using (StreamReader APIData = new StreamReader(stream))
{
while (!APIData.EndOfStream)
{
var quoteLine = APIData.ReadLine();
var quoteFields = quoteLine.Split(',');
var QHItem = new QuoteHistoryItem(Symbol, quoteFields);
if (QHItem.Time > new DateTime(1900, 1, 1))
{
Add(QHItem);
} // if
} // while
} // streamreader
} // memory stream
} // webclient
} // LoadQuoteHistory
public class QuoteHistoryItem
{
public string Symbol { get; set; }
public DateTime Time { get; set; }
public decimal Opn { get; set; }
public decimal High { get; set; }
public decimal Low { get; set; }
public decimal Clos { get; set; }
public int Volm { get; set; }
public QuoteHistoryItem(string symbol, string[] quoteFields)
{
if (quoteFields != null && quoteFields.Length > 5)
{
try
{
Symbol = symbol;
DateTime.TryParse(quoteFields[0], out DateTime time);
Time = time;
decimal.TryParse(quoteFields[1], out decimal opn);
Opn = opn;
decimal.TryParse(quoteFields[2], out decimal high);
High = high;
decimal.TryParse(quoteFields[3], out decimal low);
Low = low;
decimal.TryParse(quoteFields[4], out decimal clos);
Clos = clos;
int.TryParse(quoteFields[5], out int volm);
Volm = volm;
}
catch (FormatException fx)
{
Console.Error.WriteLine(fx.Message);
}
}
} // method QuoteHistoryItem

Related

Read delimited file and transform to a positional layout

I have a .txt file with this example, with a lot of lines:
20200610;My name ;00000001;Name of my company for example; this is the end;01;
I need to transform this layout to a positional one. the first column with 10 chars, the second one with 30, etc. after this, generate a new file with this new layout.
20200610 My name 00000001(etc)
How can I do this transformation in C#? the file is already read.
Assuming a very simple (no quoted fields) input, use String.Split then use String.Format with the alignment component, interpolating in the field lengths.
For example:
var src = "20200610;My name ;00000001;Name of my company for example; this is the end;01;";
var fieldLens = new[] { 10, 30, 8, 30, 30, 2, 1 };
var res = src.Split(';').Select((s, n) => String.Format($"{{0,{-fieldLens[n]}}}", s)).Join();
A possible solution by creating a string extension method
// StringExtension.cs
public static class StringExtension
{
public static String ToCustomLength(this String value, int cnt)
{
if (value.Length == cnt)
return value;
else if (value.Length < cnt)
value = value.PadRight(cnt, ' ');
else
value = value.Substring(0, cnt);
return value;
}
}
// Program.cs
class cData
{
public string SomeDate { get; set; }
public string SomeName { get; set; }
public string SomeID { get; set; }
public string SomeCompany { get; set; }
public string SomeCompany2 { get; set; }
public string SomeID2 { get; set; }
public cData(string t)
{
// Enforce the rules here
string[] t2 = t.Split(';');
if (t2.Count() != 7)
throw new Exception("Invalid String passed");
SomeDate = t2[0].ToCustomLength(10);
SomeName = t2[1].ToCustomLength(30);
SomeID = t2[2].ToCustomLength(20);
SomeCompany = t2[3].ToCustomLength(30);
SomeCompany2 = t2[4].ToCustomLength(30);
SomeID2 = t2[5].ToCustomLength(5);
}
}
class Program
{
static void Main(string[] args)
{
cData data = new cData("20200610; My name; 00000001; Name of my company for example; this is the end; 01;");
}
}

How to pass a value from within a List up to a method? MessagingCenter?

I have created a List object for charting in SyncFusion. I have performed a calculation at the end of the List creation that gets the Minimum value of one of the objects in the List (which is 'close'), and ascribes it to a variable called 'AxisMinimum'. That works fine.
I now need to take that variable's value and pass it up into another method that can then use it and make an adjustment to the chart. That method is called 'NumbericalAxis_ActualRangeChanged'.
Trying to use AxisMinimum in the 'NumbericalAxis_ActualRangeChanged' method generates an error as it doesn't exist in the current context. Would using a Messaging.Center approach be appropriate or is there a better way?
[DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private void NumericalAxis_ActualRangeChanged(object sender, ActualRangeChangedEventArgs e)
{
e.ActualMinimum = AxisMinimum;
}
}
public class SaleInfo
{
public string date { get; set; }
public string minute { get; set; }
public string label { get; set; }
public double high { get; set; }
public double low { get; set; }
public double open { get; set; }
public double close { get; set; }
public double average { get; set; }
public int volume { get; set; }
public double notional { get; set; }
public int numberOfTrades { get; set; }
}
public class SalesViewModel
{
public List<SaleInfo> SalesData { get; set; }
public SalesViewModel()
{
SalesData = new List<SaleInfo>();
SalesData.Add(new SaleInfo { date = "2019-08-16", minute = "09:30", label = "09:30 AM", high = 204.84, low = 204.05, open = 204.3, close = 904.75, average = 204.508, volume = 8709, notional = 1781061.51, numberOfTrades = 69 });
SalesData.Add(new SaleInfo { date = "2019-08-16", minute = "09:31", label = "09:31 AM", high = 204.8, low = 204.46, open = 204.8, close = 904.5, average = 204.622, volume = 5783, notional = 1183329.75, numberOfTrades = 58 });
SalesData.Add(new SaleInfo { date = "2019-08-16", minute = "09:32", label = "09:32 AM", high = 204.72, low = 204.34, open = 204.46, close = 904.36, average = 204.548, volume = 4468, notional = 913920.6, numberOfTrades = 50 });
SalesData.Add(new SaleInfo { date = "2019-08-16", minute = "09:33", label = "09:33 AM", high = 204.41, low = 204.06, open = 204.39, close = 904.06, average = 204.243, volume = 1834, notional = 374581.99, numberOfTrades = 22 });
double AxisMinimum = SalesData.Min(SaleInfo => SaleInfo.close);
}
}
Thanks Çöđěxěŕ, that did the trick. Using the following code made it work...
public void NumericalAxis_ActualRangeChanged(object sender, ActualRangeChangedEventArgs e)
{
SalesViewModel p = new SalesViewModel();
e.ActualMinimum = p.AxisMinimum;
}
By creating an instance of SalesViewModel object I could then get at that variable and use it. Thanks.
In the above solution, doesn't provide you with the correct value of AxisMinium (min value of Close property values in SaleInfo). Because each time, you are creating a new instance of SalesViewModel.
SalesViewModel p = new SalesViewModel();
It has been modified by
public void NumericalAxis_ActualRangeChanged(object sender,ActualRangeChangedEventArgs e){
SalesViewModel p = (sender as Axis).BindingContext as SalesViewModel;
if(p != null )
{
e.ActualMinimum = p.AxisMinimum;
}}

How to Create Compound Dataset on HDF5 C#

i need to write some data to a HDF5 file, i have a list of objects of the class "OPC_UA" inside a "BV" class, i want to create a dataset with the name of the BV and inside the dataset i want to have the list of the "OPC_UA" objects, tha OPC_UA Class have 3 attributes, a Long int ,one float value and a Datetime that i will convert to a timestamp, i can't seem to make it work, the Marshal.SizeOf() doesn't work with classes but i cant do it as a struct... Here is my code:
public void CriaHDF5Customizado(PackingConfigFile pf)
{
H5FileId fileId = H5F.create("pmdfq.h5", H5F.CreateMode.ACC_TRUNC);
H5GroupId infoGroupId = H5G.create(fileId, "informations");
H5G.close(infoGroupId);
H5GroupId datasetGroupId = H5G.create(fileId, "datasets");
long[] dims = new long[1];
foreach(BasicVariable bv in pf.basicVariableList.bvList)
{
OPC_UA aux = new OPC_UA();
var xx = bv.bvData;
int tamanho = Marshal.SizeOf(typeof(OPC_UA));
dims[0] = (long)bv.bvData.Count;
// dims[1] = (long)4;
H5DataSpaceId spaceId = H5S.create(H5S.H5SClass.SCALAR);
H5DataTypeId dataTypeId = H5T.create(H5T.CreateClass.COMPOUND, Marshal.SizeOf(typeof(OPC_UA)));
H5T.insert(dataTypeId, "TimeStamp", 0, new H5DataTypeId(H5T.H5Type.NATIVE_UINT));
H5T.insert(dataTypeId, "Quality", Marshal.SizeOf(H5T.H5Type.NATIVE_UINT), new H5DataTypeId(H5T.H5Type.NATIVE_UINT));
H5T.insert(dataTypeId, "Value", 2* Marshal.SizeOf(H5T.H5Type.NATIVE_UINT), new H5DataTypeId(H5T.H5Type.NATIVE_INT));
H5DataSetId dataSetId = H5D.create(datasetGroupId, bv.bvTag, dataTypeId, spaceId);
//H5D.write(dataSetId, new H5DataTypeId(H5T.H5Type.STD_REF_OBJ), new H5Array<OPC_UA>(bv.bvData.ToArray()));
H5D.writeScalar(dataSetId, dataTypeId, ref xx);
H5D.close(dataSetId);
}
H5G.close(datasetGroupId);
H5F.close(fileId);
}
And this is the OPC UA Class
public class OPC_UA
{
public DateTime timeStamp { get; set; }
public string data { get; set; }
public Int64 quality { get; set; }
public OPC_UA(DateTime? ts = null ,string dt = "",Int64 qlt = -99)
{
if (!ts.HasValue)
{
timeStamp = DateTime.Now;
}
data = dt;
quality = qlt;
}
public DateTime timeStamp { get; set; }
DateTime is not an atomic datatype. Convert it into long/Int64 ticks. Then you might be able to write it.
public DateTime timeStamp
{
get { return new DateTime(StartTimeTicks); }
set
{
StartTimeTicks = value.Ticks;
}
}
public long StartTimeTicks;
The constructor may also be hindering it.
The workaround would be making a structure. Note: Make the structure of fields or properties, depending upon (GetFields)fields or (GetProperties)properties you will to use in the reflection to read it.
public structure OPC_UA
{
public string data;
public Int64 quality ;
public DateTime timeStamp
{
get { return new DateTime(StartTimeTicks); }
set
{
StartTimeTicks = value.Ticks;
}
}
public long StartTimeTicks;
}
Hdf5DotnetTools is a working C# wrapper on Hdf.PInvoke. You can write a compound dataset by using a C# structure list.
If you have any difficulty in using the functions of either Hdf.PInvoke or Hdf5DotnetTools, you can use its UnitTest project.

Converting the result of Func<T, IConvertible> to int in a lambda expression

I am abstracting a bit of code, and ran into an issue with casting the result of a Func to an integer for comparison.
I have a function:
public static IConvertible GetIllnessRateByParity(IEnumerable<ILLNESS_OBJECT> pItems, int pParity, Func<ILLNESS_OBJECT, IConvertible> pSelector)
{
var filtered = pItems.Where(a => a.Parity == pParity);
return Math.Round(filtered.Count(a => Convert.ToInt32(pSelector(a)) == 1) / (double)GetBirthCountByParity(pItems, pParity), 2);
}
public class ILLNESS_OBJECT
{
public int ID { get; set; }
public DateTime Day { get; set; }
public int Parity { get; set; }
public int Afterbirth { get; set; }
public int OvaryInfection { get; set; }
etc...
}
Which calculates the rate of a specific illness within a set of data. The illness to be analysed is input through a selector, which selects an IConvertible value from the ILLNESS_OBJECT object.
I call the method like this:
GetIllnessRateByParity(data, 1, a => a.AfterBirth)
data is an IEnumerable with non-null values.
The method throws an InvalidCastException at the Convert.ToInt32(pSelector(a)) part without clear indication of why this cast fails, could anyone explain it to me? I am under the impression that pSelector(a) returns an IConvertible value which is cast-compatible with int, right? Any help would be greatly appreciated!
EDIT: Exception message:
An exception of type 'System.InvalidCastException' occurred in CONFIDENTIAL.CLASS.dll but was not handled in user code
Message: Specified cast is not valid.
The last parameter is called pSelector, but it's not actually a selector.
It's just returning a value (int, float...), and the actual selection is being done by the labmda in the Count method:
filtered.Count(a => Convert.ToInt32(pSelector(a)) == 1)
So pSelector is going to return a value of some data type, and then you're relying on being able to convert that to an int32.
But you only need to do that to compare it to 1. Given the info in your question, you don't really need an int32, you need a bool.
So what if you refactor pSelector to be a selector, by moving the comparison to 1 inside the selector:
public static double GetIllnessRateByParity(IEnumerable<ILLNESS_OBJECT> pItems, int pParity, Func<ILLNESS_OBJECT, bool> pSelector)
{
var filtered = pItems.Where(a => a.Parity == pParity);
return Math.Round(filtered.Count(pSelector) / (double)GetBirthCountByParity(pItems, pParity), 2);
}
GetIllnessRateByParity(data, 1, a => a.AfterBirth==1)
Check this
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var data = new List<ILLNESS_OBJECT>{
new ILLNESS_OBJECT{ ID = 1, Parity = 1, Day = DateTime.Now, SomeString = "1", Long = 2L},
new ILLNESS_OBJECT{ ID = 2, Parity = 2, Day = DateTime.Now, SomeString = "1", Long = 2L},
new ILLNESS_OBJECT{ ID = 3, Parity = 1, Day = DateTime.Now, SomeString = "2", Long = 1L},
new ILLNESS_OBJECT{ ID = 4, Parity = 1, Day = DateTime.Now, SomeString = "3", Long = 3L},
};
Console.WriteLine(GetIllnessRateByParity(data, 1, x => x.ID));
Console.WriteLine(GetIllnessRateByParity(data, 1, x => int.Parse(x.SomeString)));
Console.WriteLine(GetIllnessRateByParity(data, 1, x => (DateTime.Now - x.Day).Days + 1));
Console.WriteLine(GetIllnessRateByParity(data, 1, x => (int)x.Long));
}
public static IConvertible GetIllnessRateByParity(IEnumerable<ILLNESS_OBJECT> pItems, int pParity, Func<ILLNESS_OBJECT, int> pSelector)
{
var filtered = pItems.Where(a => a.Parity == pParity);
return Math.Round(filtered.Count(a => pSelector(a) == 1)/(double)1, 2);
}
}
public class ILLNESS_OBJECT
{
public int ID { get; set; }
public DateTime Day { get; set; }
public int Parity { get; set; }
public int Afterbirth { get; set; }
public string SomeString { get; set; }
public long Long { get; set; }
}

Parsing text file using C#

Looking for a good way to parse out of this text file, the values highlighted with the yellow boxes using C#. Each section is delineated by a TERM # which I forgot to highlight. Tried this:
string fileName = "ATMTerminalTotals.txt";
StreamReader sr = new StreamReader(fileName);
string[] delimiter = new string[] { " " };
while (!sr.EndOfStream)
{
string[] lines = sr.ReadLine().Split(delimiter, StringSplitOptions.RemoveEmptyEntries);
foreach (string line in lines)
{
Console.WriteLine(line);
}
}
Console.ReadLine();
Safe to say I am reading lines correctly and removing "white spaces." Although, as an amateur to programming, not sure of a valid way to accurately "know" that I am getting the values from this report that I need. Any advice?
i've tested this with a very simple program to parse the given file,
basically i've created two basic classes, a page class holding a collection of terminal report class (the tran type rows)
these rows maybe even can be represented as transaction and a billing class too
first parsed the data, setting the parameters needed and lastly just accessing the properties
just rushed it to be as simple as possible, no error handling etc... its just to give you a sense of how id start solving these kind of tasks, hope it helps
Adam
namespace TerminalTest
{
class Program
{
public class TerminalReport
{
public string Word { get; set; }
public int Denials { get; set; }
public int Approvals { get; set; }
public int Reversals { get; set; }
public double Amount { get; set; }
public int ON_US { get; set; }
public int Alphalink { get; set; }
public int Interchange { get; set; }
public int Surcharged { get; set; }
public static TerminalReport FromLine(string line)
{
TerminalReport report = new TerminalReport();
report.Word = line.Substring(0, 11);
line = line.Replace(report.Word, string.Empty).Trim();
string[] split = line.Split(' ');
int i = 0;
// transaction summary
report.Denials = int.Parse(split[i++]);
report.Approvals = int.Parse(split[i++]);
report.Reversals = int.Parse(split[i++]);
report.Amount = double.Parse(split[i++]);
// billing counts
report.ON_US = int.Parse(split[i++]);
report.Alphalink = int.Parse(split[i++]);
report.Interchange = int.Parse(split[i++]);
report.Surcharged = int.Parse(split[i++]);
return report;
}
}
public class TerminalPage
{
public int PageNumber { get; set; }
public double TotalSurcharges { get; set; }
public List<TerminalReport> Rows { get; set; }
public TerminalPage(int num)
{
PageNumber = num;
Rows = new List<TerminalReport>();
}
public int TotalDenials
{
get
{
return rows.Sum(r => r.Denials);
}
}
public int TotalApprovals
{
get
{
return Rows.Sum(r => r.Approvals;
}
}
public int TotalReversals
{
get
{
return Rows.Sum(r => r.Reversals;
}
}
public double TotalAmount
{
get
{
return Rows.Sum(r => r.Amount);
}
}
public int TotalON_US
{
get
{
return Rows.Sum(r => r.ON_US);
}
}
public int TotalAlphalink
{
get
{
return Rows.Sum(r => r.Alphalink);
}
}
public int TotalInterchange
{
get
{
return Rows.Sum(r => r.Interchange);
}
}
public int TotalSurcharged
{
get
{
return Rows.Sum(r => r.Surcharged);
}
}
}
private static string CleanString(string text)
{
return Regex.Replace(text, #"\s+", " ").Replace(",", string.Empty).Trim();
}
private static List<TerminalPage> ParseData(string filename)
{
using (StreamReader sr = new StreamReader(File.OpenRead(filename)))
{
List<TerminalPage> pages = new List<TerminalPage>();
int pageNumber = 1;
TerminalPage page = null;
bool parse = false;
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
line = CleanString(line);
if (line.StartsWith("TRAN TYPE"))
{
// get rid of the ----- line
sr.ReadLine();
parse = true;
if (page != null)
{
pages.Add(page);
}
page = new TerminalPage(pageNumber++);
}
else if (line.StartsWith("="))
{
parse = false;
}
else if (line.StartsWith("TOTAL SURCHARGES:"))
{
line = line.Replace("TOTAL SURCHARGES:", string.Empty).Trim();
page.TotalSurcharges = double.Parse(line);
}
else if (parse)
{
TerminalReport r = TerminalReport.FromLine(line);
page.Rows.Add(r);
}
}
if (page != null)
{
pages.Add(page);
}
return pages;
}
}
static void Main(string[] args)
{
string filename = #"C:\bftransactionsp.txt";
List<TerminalPage> pages = ParseData(filename);
foreach (TerminalPage page in pages)
{
Console.WriteLine("TotalSurcharges: {0}", page.TotalSurcharges);
foreach (TerminalReport r in page.Rows)
Console.WriteLine(r.Approvals);
}
}
}
}
I'm not sure I'd split it by spaces actually.. the textfile looks like its split into columns. You might want to read like 10 chars (or whatever the width of the column is) at a time... and I'd parse the whole file into a dictionary so you get entries like
dict["WDL FRM CHK"]["# DENIALS"] = 236
then you can easily retrieve the values you want from there, and if you ever need more values in the future, you've got them.
Alternatively, you can use regexs. You can grab the first value with a regex like
^WDL FRM CHK\s+(?<denials>[0-9,]+)\s+(?<approvals>[0-9,]+)$
using
m.Groups["approvals"]
anyway I recommend you to wrap your StreamReader with using block:
using (StreamReader sr = new StreamReader(fileName))
{
// do stuff
}
Read more on MSDN
Given that it seems to have a standard, regular format, I would use regular expressions. You can check the starting code to figure out what row you're on, then an expression that will parse out the numbers and ignore whitespace will, very likely, be easier than handling it manually.
using System;
using System.Text.RegularExpressions;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
Regex exp = new Regex(#"WDL FRM CHK(\s)+[1-9,]+(\s)+(?<approvals>[1-9,]+)(\s)+");
string str = "WDL FRM CHK 236 1,854 45,465 123 3";
Match match = exp.Match(str);
if (match.Success)
{
Console.WriteLine("Approvals: " + match.Groups["approvals"].Value);
}
Console.ReadLine();
}
}
}
Apdated from the following article to parse one of your numbers:
How to match a pattern by using regular expressions and Visual C#

Categories