I have the following class:
public class VendorClass {
public int VendorID { get; set; }
public string VendorName { get; set; }
}
The fields above match fields in the database table.
In the case of say VendorName, how do I give it a field width ?
VendorName maps to a field in the database which is varchar(15)
You can't limit the length of the string but you can use properties with backing fields to achieve the desired result :
public class VendorClass
{
public int VendorID { get; set; }
private string _vendorName;
public string VendorName
{
get { return _vendorName; }
set
{
if (value.Length > 15)
{
_vendorName = value.Substring(0,15);
} else {
_vendorName = value;
}
}
}
}
Strings in C# have almost-arbitrary length.
When loading from your database, it will automatically accommodate the actual string length. When saving to the database, your business logic, data layer or ORM (as appropriate) will need to ensure the proper maximum length.
A string can't have a set length in C#. You will have to handle the db length through some other mechanism like validation. Can't really tell you more without more details.
I would question why you would do this in c# code. However this link has a couple of ways around this. I suppose either truncation or taking a subsring is the best option. You could also make sure that the UI (or the model-view) takes care of details such as this.
I am not sure exactly what you are asking, but if you want to know the maximum length of a string, this question can help you.
If you want to limit the number of characters entered, I would suggest that you use server-side validation and/or client-side validation.
I just met a problem like what you described and found a way to create a limited length's string. Maybe a little inflexible but concise when there are only finite varchar length definitions in database.
Firstly introduce some basic classes:
public class Length16
{
public static int StringLength { get => 16; }
}
public class Length8
{
public static int StringLength { get => 8; }
}
public class Length15
{
public static int StringLength { get => 15; }
}
public class LimitedLengthString<T>
{
private string _sValue;
public LimitedLengthString(string sNewValue)
{
_sValue = sNewValue;
}
public static implicit operator LimitedLengthString<T>(string sNewValue)
{
var prop = typeof(T).GetProperty("StringLength");
int iLength = (int)prop.GetValue(null);
if (sNewValue.Length > iLength)
{
throw new Exception($"New string is too long! Allowed length {iLength}.");
}
return new LimitedLengthString<T>(sNewValue);
}
public static implicit operator string(LimitedLengthString<T> sSource)
{
return sSource.ToString();
}
public override string ToString()
{
return _sValue;
}
}
public class AutoTruncatedString<T>
{
private string _sValue;
public AutoTruncatedString(string sNewValue)
{
_sValue = sNewValue;
}
public static implicit operator AutoTruncatedString<T>(string sNewValue)
{
var prop = typeof(T).GetProperty("StringLength");
int iLength = (int)prop.GetValue(null);
return new AutoTruncatedString<T>(sNewValue.Substring(0, iLength));
}
public static implicit operator string(AutoTruncatedString<T> sSource)
{
return sSource.ToString();
}
public override string ToString()
{
return _sValue;
}
}
Use them like this:
LimitedLengthString<Length8> sLimitedLength8;
sLimitedLength8 = "asdfgasdfg"; // will error out
AutoTruncatedString<Length8> sAutoTruncated8;
sAutoTruncated8 = "asdfgasdfg"; // will be truncated
sLimitedLength8 will throw an error if you try to assign a string longer than 8 and sAutoTruncated8 will truncate the string you assign to it.
For you, you can define the VendorName this way:
public LimitedLengthString<Length15> VendorName { get; set; }
Hope this could help you.
Related
I have Sprache set up to parse an Equation that has a number of different possible method calls in it. After it resolves the method, is there a way to determine the index values within the original string? Perhaps the Parse has a "current index" value and "length" value that's somehow accessible?
Example input string:
IndexOf("fred", 2) + IndexOf("bob")
using a parser like this...
Parser<Expression> FunctionCall = from namePart in Parse.Letter.Many().Text()
from lparen in Parse.Char('(')
from expr in Parameter.DelimitedBy(ListDelimiter)
from rparen in Parse.Char(')')
select CallMethod(namePart, Enumerable.Repeat(sourceData, 1)
.Concat(expr)
.ToArray());
Can anyone think of a "trick" that would allow me to determine that the first CallMethod handles SubString(0, 18), and the second CallMethod handles SubString(21, 14) from the original string?
If you use a generic class and extension method you can make a more general approach
public class PositionAware<T> : IPositionAware<PositionAware<T>>
{
public PositionAware(T value)
{
Value = value;
}
public T Value { get; }
public Position Start { get; private set; }
public int Length { get; private set; }
public PositionAware<T> SetPos(Position startPos, int length)
{
Start = startPos;
Length = length;
return this;
}
}
public static Parser<PositionAware<T>> WithPosition<T>(this Parser<T> value)
{
return value.Select(x => new PositionAware<T>(x)).Positioned();
}
Using it:
from c in Parse.Char('a').WithPosition()
select (c.Start, c.Value)
from c in Parameter.DelimitedBy(ListDelimiter).WithPosition()
select (c.Start, c.Value)
I've managed to answer my own question. It's the Positioned() parser extension call that allows a parser to track the position within the original text.
Parser<Expression> FunctionCall = (from namePart in Parse.Letter.Many().Text()
from lparen in Parse.Char('(')
from expr in Parameter.DelimitedBy(ListDelimiter)
from rparen in Parse.Char(')')
select new MethodPosAware(namePart, expr)).Positioned()
.Select(x => CallMethod(x.Value, Enumerable.Repeat(sourceData, 1)
.Concat(x.Params)
.ToArray(),
x.Pos.Pos, x.Length));
I had to make a new MethodPosAware class to keep the position information, that derives from Sprache's IPositionAware:
class MethodPosAware : IPositionAware<MethodPosAware>
{
public MethodPosAware(string methodName, IEnumerable<Expression> parameters)
{
Value = methodName;
Params = parameters;
}
public MethodPosAware SetPos(Position startPos, int length)
{
Pos = startPos;
Length = length;
return this;
}
public Position Pos { get; set; }
public int Length { get; set; }
public string Value { get; set; }
public IEnumerable<Expression> Params { get; set; }
}
I think I'll be extending this further to work with more than just Method names, but this is sufficient to answer my question for now. I hope this helps someone down the road.
I have the following:
public class Broadcast {
public int NumUsersToMessage { get; set; }
public int NumMessagesQueued { get; set; }
public string DbUsersMessaged { get; set; }
public int NumMessagesSent {
get {
return UsersMessaged.Count();
}
}
public List<int> UsersMessaged {
get {
return DbUsersMessaged == null ? new List<int>() : DbUsersMessaged.Split(',').Select(Int32.Parse).ToList();
}
set {
DbUsersMessaged = value != null ? String.Join(",", value) : null;
}
}
}
My goal here is to only ever access DbUsersMessaged through UsersMessaged. I'm attempting to do broadcast.UsersMessaged.Add(2), however since this is not an assignment, I can't get the property to behave as I like. Instead, I have to do this:
tempList = broadcast.UsersMessaged();
tempList.Add(2);
broadcast.UsersMessaged = tempList;
db.SaveChanges();
Which is obviously unwieldy. I'm considering making an AddReassign extension method but I want to know - what's the standard practice here for supporting Lists of primitive types? It looks like even with the extension method, my best shot looks like this:
broadcast.UsersMessaged = broadcast.UsersMessaged.AddReassign(2) // yuck!
Before anyone asks - we've intentionally denormalized this for performance reasons.
If you don't care about performance, you can create own list:
public class MyList : IList<int>
{
private List<int> underlyingList;
private Broadcast entity;
public MyList(Broadcast entity)
{
this.entity = entity;
this.underlyingList = entity.DbUsersMessaged?.Split(",") ?? new List<int>();
}
public void Add(int i)
{
this.underlyingList.Add(i);
this.entity.DbUsersMessaged = String.Join(",", underylingList);
}
// other interface memebers impl
}
Then
MyList list;
public IList<int> UsersMessaged {
get {
return myList ?? (myList = new MyList(this));
}
}
Of course it is only sample.
I recommend you to have a look at this: Entity Framework 5 - Looking for Central Point to Execute Custom Code after Entity is Loaded from Database
And then convert from string to list, and then use Saving Changes event to convert back into the string construction when saving.
Then, for performance, maybe you want to use byte[] rather than a string for storing the data in the database.
I wish to create an online quiz that can ask any question from thousands of programmed questions. Each question is created via a function that is given an array of int whose values determine the exact question displayed. I have each question as a class:
public class AddingTwoDigitNumbers : IQuestion
{
public string QName() { return "Adding Two-Digit Numbers" };
public int[] QParams() { return int[]() {Random(10, 99), Random(10, 99) };
public void Question(int[] values) {
Console.WriteLine(string.Format("What is {1} + {2}?", values[0], values[1]);
}
public void Answer(int[] values) {
Console.WriteLine(values[0] + values[1]).ToString());
}
}
QParams creates the array of int (to determine exactly the question created), that is given to both Question and Answer to create the question and answer.
I want a List of questions searchable by QName but would rather not have to create (and name) thousands of classes all implementing IQuestion.
So here is my second solution:
public class Question
{
public string QName { get; set; }
public Func<int[]> QParams { get; set; }
public Action<int[]> Question { get; set; }
public Action<int[]> Answer { get; set; }
}
public class QuestionRepository
{
public static Dictionary<string, Question> Questions = new Dictionary<string, Question>();
public static void AddQuestions(Question[] qs) {
foreach (Question q in qs) Questions.Add(q.QName, q);
}
}
public class FirstSetOfQuestions
{
static void AddQuestions()
{
QuestionRepository.AddQuestions(new Question[]
{
new Question()
{
QName = "Adding Two-Digit Numbers",
QParams = () => int[]() {Random(10, 99), Random(10, 99) },
Question = (v) => {Console.WriteLine(string.Format("What is {1} + {2}?", v[0], v[1]);},
Answer = (v) => {Console.WriteLine(values[0] + values[1]).ToString());}
},
new Question()
{
QName = "Subtracting Three-Digit Numbers",
QParams = () => int[]() {Random(100, 999), Random(100, 999) },
Question = (v) => {Console.WriteLine(string.Format("What is {1} - {2}?", v[0], v[1]);},
Answer = (v) => {Console.WriteLine(values[0] - values[1]).ToString());}
}
}
}
}
So my question is which is better? Do I create thousands of classes, having to provide a name for each one, or do I create thousands of anonymous functions and a class that stores these using (I assume) delegates? Is there a problem with the second solution if I have thousands of questions, or even a better way to do this?
(Obviously the questions I wish to create are much more complicated than shown here, and involve fractions, algebra etc.)
Just to get you started with fluent syntax, throwing in some stubs and ideas in there as well.
class Question
{
public string Name { get; set; }
public string QuestionFormat { get; set; }
public List<Range> Args { get; set; }
public Expression<Func<int[], int>> ValExp { get; set; }
public Question(string name, string questionFormat)
{
this.Name = name;
this.QuestionFormat = questionFormat;
this.Args = new List<Range>();
}
public Question Rand(int min, int max)
{
this.Args.Add(new Range(min, max));
return this;
}
public void Val(Expression<Func<int[], int>> exp)
{
this.ValExp = exp;
}
public CompiledQuestion Compile()
{
// Generate args in the appropriate ranges
// Evaluate the result with the ValExp
// Return a new CompiledQuestion with the information -
// basically just replacing Args, ValExp with RealArgs, Val
}
public ICoolDataObject Save()
{
}
public static Question Load(ICoolDataObject hmm)
{
}
}
class Range
{
public int Min { get; set; }
public int Max { get; set; }
public Range(int min, int max)
{
this.Min = min;
this.Max = max;
}
}
It's almost fun, creating questions now:
new Question("simple addition",
"whats {0} + {1}?")
.Rand(10, 99)
.Rand(10, 99)
.Val(v => v[0] + v[1]);
You can obviously add some validation checks to avoid bad number of arguments due to late hours of work, and use double or decimal instead of int wherever.
Both approaches are wrong. I presume you are not going to have thousands of different types of calculations. You are only going to have a dozen or a few dozen different types of calculations, operating on a huge variety of data.
So, you need to normalize your data so as to end up with about a dozen or a few dozen different well defined calculations on a database of well defined data, end then write about a dozen or a few dozen classes, one for each kind of calculation, only.
You might think that this is too complicated, and you might think that writing thousands of classes (or delegates, it does not really matter) might be a lot of work but each piece is small and easy, but trust me, you will bitterly regret doing it this way as soon as something needs to change on the interface or the implementation of all of these classes, and most chances are that something will need to change at some point in time.
I have a string with the following structure:
Student Name________AgeAddress_______________________Bithday___Lvl
Example:
Jonh Smith 016Some place in NY, USA 01/01/2014L01
As you can see, there is no delimited character like | or ,
Also, there is no space between fields (if you check, there is no space between Age/Address and Birthday/Level.
The size of each field is static so if data's length is less then it will contains white spaces.
I have a class that need to be filled with that information:
public class StudentData
{
public char[] _name = new char[20];
public string name;
public char[] _age = new char[3];
public string age;
public char[] _address = new char[30];
public string address;
public char[] _bday = new char[10];
public string bday;
public char[] _level = new char[3];
public string level;
}
Is there any way to do this automatically and dynamically?
I mean I really don't want to code like this:
myClass.name = stringLine.substring(0,19);
myClass.age = stringLine.substring(20,22);
That's because I have way more fields that the ones added in this example & way more string lines with other different data.
Update: There were supposed to be a lot of spaces between "Smith" and "016", but I don't know how to edit it.
Update2: If I use StringReader.Read() I can evade to use substring and indexes, but it isn't still so dynamically because I would need to repeat those 3 lines for each field.
StringReader reader = new StringReader(stringLine);
reader.Read(myClass._name, 0 myClass._name.Length);
myClass.name = new string(myClass._name);
Given your requirement I came up with an interesting solution. All be-it it may be more complex and longer than using the String.SubString() method as stated.
However this solution is transferable to other types and other string. I used a concept of Attributes, Properties, and Reflection to parse a string by a Fixed Length and setting the class Properties.
Note I did change your StudentData class to follow a more conventional coding style. Following this handy guide on MSDN: http://msdn.microsoft.com/en-us/library/xzf533w0(v=vs.71).aspx
Here is the new StudentData class. Note it uses the properties as opposed to fields. (Not discussed here).
public class StudentData
{
string name;
string age;
string address;
string bday;
string level;
[FixedLengthDelimeter(0, 20)]
public string Name { get { return this.name; } set { this.name = value; } }
[FixedLengthDelimeter(1, 3)]
public string Age { get { return this.age; } set { this.age = value; } }
[FixedLengthDelimeter(2, 30)]
public string Address { get { return this.address; } set { this.address = value; } }
[FixedLengthDelimeter(3, 10)]
public string BDay { get { return this.bday; } set { this.bday = value; } }
[FixedLengthDelimeter(4, 3)]
public string Level { get { return this.level; } set { this.level = value; } }
}
Note on each of the properties there is an Attribute called FixedLengthDelimeter that takes two parameters.
OrderNumber
FixedLength
The OrderNumber parameter denotes the order in the string (not the position) but the order in which we process from the string. The second parameter denotes the Length of the string when parsing the string. Here is the full attribute class.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class FixedLengthDelimeterAttribute : Attribute
{
public FixedLengthDelimeterAttribute(int orderNumber, int fixedLength)
{
this.fixedLength = fixedLength;
this.orderNumber = orderNumber;
}
readonly int fixedLength;
readonly int orderNumber;
public int FixedLength { get { return this.fixedLength; } }
public int OrderNumber { get { return this.orderNumber; } }
}
Now the attribute is simple enough. Accepts the two paramters we discussed eariler in the constructor.
Finally there is another method to parse the string into the object type such as.
public static class FixedLengthFormatter
{
public static T ParseString<T>(string inputString)
{
Type tType = typeof(T);
var properties = tType.GetProperties(BindingFlags.Instance | BindingFlags.Public); //;.Where(x => x.GetCustomAttributes(typeof(FixedLengthDelimeterAttribute), false).Count() > 0);
T newT = (T)Activator.CreateInstance(tType);
Dictionary<PropertyInfo, FixedLengthDelimeterAttribute> dictionary = new Dictionary<PropertyInfo, FixedLengthDelimeterAttribute>();
foreach (var property in properties)
{
var atts = property.GetCustomAttributes(typeof(FixedLengthDelimeterAttribute), false);
if (atts.Length == 0)
continue;
dictionary[property] = atts[0] as FixedLengthDelimeterAttribute;
}
foreach (var kvp in dictionary.OrderBy(x => x.Value.OrderNumber))
{
int length = kvp.Value.FixedLength;
if (inputString.Length < length)
throw new Exception("error on attribute order number:" + kvp.Value.OrderNumber + " the string is too short.");
string piece = inputString.Substring(0, length);
inputString = inputString.Substring(length);
kvp.Key.SetValue(newT, piece.Trim(), null);
}
return newT;
}
}
The method above is what does the string parsing. It is a pretty basic utility that reads all the properties that have the FixedLengthDelimeter attribute applied a Dictionary. That dictionary is then enumerated (ordered by OrderNumber) and then calling the SubString() method twice on the input string.
The first substring is to parse the next Token while the second substring resets the inputString to start processing the next token.
Finally as it is parsing the string it is then applying the parsed string to the property of the class Type provided to the method.
Now this can be used simply like this:
string data1 = "Jonh Smith 016Some place in NY, USA 01/01/2014L01";
StudentData student = FixedLengthFormatter.ParseString<StudentData>(data1);
What this does:
Parses a string against property attributes in a fixed length format.
What this does not do:
It does convert the parsed strings to another type. Therefore all the properties must be a string. (this can be easily adapted by adding some type casting logic in).
It is not well tested. This is only tested against a few samples.
It is not by all means the only or best solution out there.
You could use FileHelpers library (NuGet).
Just define the structure of your input file with attributes:
[FixedLengthRecord]
public class StudentData
{
[FieldFixedLength(20)]
[FieldTrim(TrimMode.Right)]
public string name;
[FieldFixedLength(3)]
public string age;
[FieldFixedLength(30)]
[FieldTrim(TrimMode.Right)]
public string address;
[FieldFixedLength(10)]
public string bday;
[FieldFixedLength(3)]
public string level;
}
Then simply read the file using FileHelperEngine<T>:
var engine = new FileHelperEngine<StudentData>();
var students = engine.ReadFile(filename);
I am creating a dataGridView which gets its values from an arrayList. To retrieve the values, I have:
public DataSet(String totalCM, String totPM, String hkCM, String hkPM, String sherCM, String sherPM, String hinsCM, String hinsPM, String kassCM, String kassPM, String belleCM, String bellePM)
{
_totalCM = totalCM;
_totalPM = totPM;
_hiddenKnollsCM = hkCM;
_hiddenKnollsPM = hkPM;
_sherCM = sherCM;
_sherPM = sherPM;
_hinsdaleCM = hinsCM;
_hinsdalePM = hinsPM;
_kassonCM = kassCM;
_kassonPM = kassPM;
_belleCM = belleCM;
_bellePM = bellePM;
}
public String TotalCurrentMonth
{
get { return _totalCM; }
}
public String TotalPreviousMonth
{
get { return _totalPM; }
}
public String HiddenKnollsCurrentMonth
{
get { return _hiddenKnollsCM; }
}
public String HiddenKnollsPreviousMonth
{
get { return _hiddenKnollsPM; }
}
public String SherwoodCurrentMonth
{
get { return _sherCM; }
}
public String SherwoodPreviousMonth
{
get { return _sherPM; }
}
public String HinsdaleCurrentMonth
{
get { return _hinsdaleCM; }
}
public String HinsdalePreviousMonth
{
get { return _hinsdalePM; }
}
public String KassonCurrentMonth
{
get { return _kassonCM; }
}
public String KassonPreviousMonth
{
get { return _kassonPM; }
}
public String BelleIsleCurrentMonth
{
get { return _belleCM; ; }
}
public String BelleIslePreviousMonth
{
get { return _bellePM; }
}
}
How do I go about creating custom column headers for this, as they need to have a space? Probably a really dumb question, but could not find much information about this specific issue. I know that you can modify the properties in the collection of column names, but it just seems to create new column header names based off of the accessor methods in the code. Thanks in advance.
Well, if you're using .NET 2+ you can use the DisplayNameAttribute Class.
Use in on your properties to specify the string used in the column headers of your DGV; otherwise the property name will be used (as you see).
And if you're using .NET 2+ you shouldn't be using an ArrayList, use a List<T> instread.