How to modify the Content in RuleAction - c#

Below is the code I have written. I need to modify the content which is available in rr
for example :
if rr.ThenAction = "this.MacroLoop.Current.Strategy.SubStrategy.Current.Block.AIN.HLOP = 0"
I need it to be modified to
"rr.ThenAction = "this.MacroLoop.Current.Strategy.SubStrategy.Current.Block.AIN.HLOP = 1"
if (!ruleSet.Validate(rv))
{
List<System.Workflow.Activities.Rules.Rule> rulesList = new List<System.Workflow.Activities.Rules.Rule>();
rulesList = ruleSet.Rules.ToList();
foreach (System.Workflow.Activities.Rules.Rule rr in rulesList)
{
// I need to modify the content in rr
}
}
Help is much appreciated.

I am not sure but are you looking for something like;
rulesList = ruleSet.Rules.ToList();
for (int i = 0; i < rulesList.Count; i++)
{
rulesList[i] = "sddfs";
if(rulesList[i].ThenAction == "this.MacroLoop.Current.Strategy.SubStrategy.Current.Block.AIN.HLOP = 0")
{
rulesList[i].ThenAction = "this.MacroLoop.Current.Strategy.SubStrategy.Current.Block.AIN.HLOP = 1";
}
}
Hope it helps...!!!
PS: if you are planning to change value of rr in foreach, then it will not work as foreach is a read only iterator that iterates dynamically classes that implement IEnumerable, but you can use item.value to make changes.

Related

How can I access multi-element List data stored in a public class?

My first question on SO:
I created this public class, so that I can store three elements in a list:
public class myMultiElementList
{
public string Role {get;set;}
public string Country {get;set;}
public int Commonality {get;set;}
}
In my main class, I then created a new list using this process:
var EmployeeRolesCountry = new List<myMultiElementList>();
var rc1 = new myMultiElementList();
rc1.Role = token.Trim();
rc1.Country = country.Trim();
rc1.Commonality = 1;
EmployeeRolesCountry.Add(rc1);
I've added data to EmployeeRolesCountry and have validated that has 472 lines. However, when I try to retrieve it as below, my ForEach loop only retrieves the final line added to the list, 472 times...
foreach (myMultiElementList tmpClass in EmployeeRolesCountry)
{
string d1Value = tmpClass.Role;
Console.WriteLine(d1Value);
string d2Value = tmpClass.Role;
Console.WriteLine(d2Value);
int d3Value = tmpClass.Commonality;
Console.WriteLine(d3Value);
}
This was the most promising of the potential solutions I found on here, so any pointers greatly appreciated.
EDIT: adding data to EmployeeRolesCountry
/*
Before this starts, data is taken in via a csvReader function and parsed
All of the process below is concerned with two fields in the csv
One is simply the Country. No processing necessary
The other is bio, and this itself needs to be parsed and cleansed several times to take roles out
To keep things making sense, I've taken much of the cleansing out
*/
private void File_upload_Click(object sender, EventArgs e)
{
int pos = 0;
var EmployeeRolesCountry = new List<myMultiElementList>();
var rc1 = new myMultiElementList();
int a = 0;
delimiter = ".";
string token;
foreach (var line in records.Take(100))
{
var fields = line.ToList();
string bio = fields[5];
string country = fields[4];
int role_count = Regex.Matches(bio, delimiter).Count;
a = bio.Length;
for (var i = 0; i < role_count; i++)
{
//here I take first role, by parsing on delimiter, then push back EmployeeRolesCountry with result
pos = bio.IndexOf('.');
if (pos != -1)
{
token = bio.Substring(0, pos);
string original_token = token;
rc1.Role = token.Trim();
rc1.Country = country.Trim();
rc1.Commonality = 1;
EmployeeRolesCountry.Add(rc1);
a = original_token.Length;
bio = bio.Remove(0, a + 1);
}
}
}
}
EDIT:
When grouped by multiple properties, this is how we iterate through the grouped items:
var employeesGroupedByRolwAndCountry = EmployeeRolesCountry.GroupBy(x => new { x.Role, x.Country });
employeesGroupedByRolwAndCountry.ToList().ForEach
(
(countryAndRole) =>
{
Console.WriteLine("Group {0}/{1}", countryAndRole.Key.Country, countryAndRole.Key.Role);
countryAndRole.ToList().ForEach
(
(multiElement) => Console.WriteLine(" : {0}", multiElement.Commonality)
);
}
);
__ ORIGINAL POST __
You are instantiating rc1 only once (outside the loop) and add the same instance to the list.
Please make sure that you do
var rc1 = new myMultiElementList();
inside the loop where you are adding the elements, and not outside.
All references are the same in your case:
var obj = new myObj();
for(i = 0; i < 5; i++)
{
obj.Prop1 = "Prop" + i;
list.Add(obj);
}
now the list has 5 elements, all pointing to the obj (the same instance, the same object in memory), and when you do
obj.Prop1 = "Prop" + 5
you update the same memory address, and all the pointers in the list points to the same instance so, you are not getting 472 copies of the LAST item, but getting the same instance 472 times.
The solution is simple. Create a new instance every time you add to your list:
for(i = 0; i < 5; i++)
{
var obj = new myObj();
obj.Prop1 = "Prop" + i;
list.Add(obj);
}
Hope this helps.

Compare list data with static string in C#

I have the following list,
String UpDownStatus = "UP";
List<db1> StockData = new List<db1>();
db1 newStock = new db1();
newStock.Date = (DateTime)reader["Date"];
newStock.High = (double)reader["High"];
newStock.Low = (double)reader["Low"];
newStock.Close = (double)reader["Close"];
newStock.Up_Down = (string)reader["Up_Down"];
StockData.Add(newStock);
The Up_Down column in my DB has the following two string : "UP" and "DOWN"
how can i compare whether the current value of
for (int i = 0; i < StockData.Count; i++)
{
if(StockData[i].Up_Down.CompareTo(UpDownStatus) != 0)
{
//do something
}
}
I know, i could reframe this statement like if (StockData[i].Up_Down=="UP") but i need a solution where I could use .CompareTo function.
If I understood your question right and you want to do something on all items which have the same up/down-status as the variable UpDownStatus, this would be the easiest way to do it:
foreach (var item in StockData.Where(e => e.Up_Down == UpDownStatus))
{
// do something
}

Use LINQ to populate controls from object array

I am just trying to find a better way to populate some RadioButtonList controls. There are a set number of these on the usercontrol.ascx. The code is what I am currently using but I am still not very good with Linq and was wondering if there's a better way to do this.
quizId1 = quiz.Items[0].questionId;
pTag1.InnerText = quiz.Items[0].QuestionText;
foreach (Question q in quiz.Items[0].AnswerChoice)
{
radiobuttonlist1.Items.Add(new ListItem(q.Value, q.answerId));
}
same for radiobuttonlist2 but using Items[1] etc.
quizId2 = quiz.Items[1].questionId;
pTag2.InnerText = quiz.Items[1].QuestionText;
foreach (Question q in quiz.Items[1].AnswerChoice)
{
radiobuttonlist2.Items.Add(new ListItem(q.Value, q.answerId));
}
Sorry, the InnerText is a server side 'P' tag, pTag1, pTag2 etc.
Try this
var listItems = (from x in quiz.Items[0].AnswerChoice
select new ListItem { Text = q.Value, Value = q.answerId }
).ToList<ListItem>();
radiobuttonlist1.DataSource = listItems;
radiobuttonlist1.DataBind();
I suppose you could do something like this:
var listItems = from q in quiz.Items[0].AnswerChoice
select new ListItem(q.Value, q.answerId);
radioButtonlist1.Items.AddRange(listItems.ToArray());
though I'm not really sure if that buys you anything other than experience with LINQ...
I assume you want to use ling to popiulate several controls, not an individual control.
Linq is for querying, not updating. To update you still need either for or foreach loops.
If your RadioButtonList objects are in a collection, you could just loop over them:
var radioList = new [] {radiobuttonlist1, radiobuttonlist2, ...};
for(int i = 0; i < quiz.Items.Length; i++)
{
var quizId = quiz.Items[i].questionId;
radioList[i].InnerText = quiz.Items[i].QuestionText;
radioList[i].Items.AddRange(quiz.Items[i]
.AnswerChoice
.Select(q => => new ListItem(q.Value, q.answerId))
.ToArray()
);
}
or use DataSource as others have suggested:
var radioList = new [] {radiobuttonlist1, radiobuttonlist2, ...};
for(int i = 0; i < quiz.Items.Length; i++)
{
var quizId = quiz.Items[i].questionId;
radioList[i].InnerText = quiz.Items[i].QuestionText;
radioList[i].DataSource = quiz.Items[i].AnswerChoice;
radioList[i].DataTextField = "Value";
radioList[i].DataValueField = "answerId";
}
but there's no Linq way to populate several controls.

Add Multiple record using Linq-to-SQL

I want to add Multiple rows into Table using Linq to SQL
public static FeedbackDatabaseDataContext context = new FeedbackDatabaseDataContext();
public static bool Insert_Question_Answer(List<QuestionClass.Tabelfields> AllList)
{
Feedback f = new Feedback();
List<Feedback> fadd = new List<Feedback>();
for (int i = 0; i < AllList.Count; i++)
{
f.Email = AllList[i].Email;
f.QuestionID = AllList[i].QuestionID;
f.Answer = AllList[i].SelectedOption;
fadd.Add(f);
}
context.Feedbacks.InsertAllOnSubmit(fadd);
context.SubmitChanges();
return true;
}
When I add records into list object i.e. fadd the record is overwrites with last value of AllList
I'm late to the party, but I thought you might want to know that the for-loop is unnecessary. Better use foreach (you don't need the index).
It gets even more interesting when you use LINQ (renamed method for clarity):
public static void InsertFeedbacks(IEnumerable<QuestionClass.Tabelfields> allList)
{
var fadd = from field in allList
select new Feedback
{
Email = field.Email,
QuestionID = field.QuestionID,
Answer = field.SelectedOption
};
context.Feedbacks.InsertAllOnSubmit(fadd);
context.SubmitChanges();
}
By the way, you shouldn't keep one data context that you access all the time; it's better to create one locally, inside a using statement, that will properly handle the database disconnection.
You should create object of Feedback in the scope of for loop, so change your method to :
public static bool Insert_Question_Answer(List<QuestionClass.Tabelfields> AllList)
{
List<Feedback> fadd = new List<Feedback>();
for (int i = 0; i < AllList.Count; i++)
{
Feedback f = new Feedback();
f.Email = AllList[i].Email;
f.QuestionID = AllList[i].QuestionID;
f.Answer = AllList[i].SelectedOption;
fadd.Add(f);
}
context.Feedbacks.InsertAllOnSubmit(fadd);
context.SubmitChanges();
return true;
}

When searching for an item in a generic list should I use LINQ or Contains?

I have a generic List and I have to find a particular string in this list. Could you please let me know which is the best approach in the below?
if (strlist.Contains("Test"))
{
// String found
}
or
string res = (from d in strlist where d == "Test" select d).SingleOrDefault();
if (res == "Test")
{
//found
}
Please consider the list may be very big populated from database. Your thoughts on this are highly appreciated.
If you have List<string> (or even IEnumerable<string>) and Contains meets your needs, then use Contains.
If you need some extra handling that Contains doesn't provide, I would suggest using Any():
if(strList.Any(s => s.StartsWith("Tes"))
{
// Found
}
The two methods will behave differently if there is more than one match; the first one will return true and the second one will throw an exception.
To correct that, change SingleOrDefault to FirstOrDefault.
To answer the question, you should call Contains if you're searching for an exact match and Any if you aren't.
For example:
if (strings.Contains("SomeString", StringComparer.OrdinalIgnoreCase))
if (strings.Any(s => s.StartsWith("b"))
You really should use HashSet<string> as the the performance of Contains is dramatically better. Now if you need to use a list for other operations you can simply have both available.
var list = BuildListOfStrings();
var set = new HashSet<string>(list);
if (set.Contains("Test"))
{
// ...
}
Now you have the ability to find items in the set as a O(1) operation.
Test
static void Main(string[] args)
{
var lst = GenerateStrings().Take(5000000).ToList();
var hsh = new HashSet<string>(lst);
var found = false;
var count = 100;
var sw = Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
hsh = new HashSet<string>(lst);
}
Console.WriteLine(TimeSpan.FromTicks(sw.ElapsedTicks / count));
sw = Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
found = lst.Contains("12345678");
}
Console.WriteLine(TimeSpan.FromTicks(sw.ElapsedTicks / count));
sw = Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
found = hsh.Contains("12345678");
}
Console.WriteLine(TimeSpan.FromTicks(sw.ElapsedTicks / count));
Console.WriteLine(found);
Console.ReadLine();
}
private static IEnumerable<string> GenerateStrings()
{
var rnd = new Random();
while (true)
{
yield return rnd.Next().ToString();
}
}
Result
0.308438 s
0.0197868 s
0.0 s
So what does this tell us? If you are making a small amount of calls to Contains use a List<string>, otherwise use a HashSet<string>.

Categories