C# Which loop to use? - c#

I can't remove the item using this type of loop (foreach), which loop should i use? (that will return my variables) if that makes any sense. Thank you all help is very much so appreciated! Be easy on me i'm not too experienced. If that doesn't make sense i'm really trying to find any way to basically make my program so that for each ip address, it will try my username and password combination (that are loaded into list like user:pass), i'm doing this because i have set up hundreds of proxies in the past with different user/pass & i'm checking to see if they work still. Thanks
var l = loadips();
var t = func();
Parallel.ForEach(l.ToArray(), (ip_item) =>
{
try
{
string ip = ip_item.IP;
try {
foreach (var blah2 in t)
{
String[] fc = blah2.test.Split(':');
var u = fc[0];
var p = fc[1];
using (var client = new ProxyClient(ip, u, p))
{
Console.WriteLine(u + p + ip_item.IP);
client.Connect();
ip_item.AcceptsConnection = client.IsConnected;
client.Disconnect();
}
}
}
catch
{
// t.Remove(blah2);
}
}
catch
{
Console.WriteLine(ip_item.IP + " - BAD!");
l.Remove(ip_item);
}
});
foreach (var item in l)
{
if (item.AcceptsConnection == true)
{
Console.WriteLine(ip + " Working proxy.");
}
}
}

Don't modify the collection through which you're iterating, whatever loop you use. To achieve your objective, simply add the working data to another list.
var working = new ConcurrentBag<IpItem>(); // not sure what your type is
[....]
using (var client = new ProxyClient(ip, u, p))
{
Console.WriteLine(u + p + ip_item.IP);
client.Connect();
ip_item.AcceptsConnection = client.IsConnected;
client.Disconnect();
working.Add(ip_item);
}
Then, at the end, get all working results from working, and output as needed

NO, you can't use foreach loop for removing an item from the collection; very basic reason because the loop iterator of foreach is ReadOnly. You should choose to use for loop for that purpose.
Check MSDN reference for foreach. As it clearly says
The foreach statement is used to iterate through the collection to get
the information that you want, but can not be used to add or remove
items from the source collection to avoid unpredictable side effects.
If you need to add or remove items from the source collection, use a
for loop.

Consider using another list to identify the failures.
var l = loadips();
var t = func();
var faileds = new ConcurrentQueue<YourClass>();
Parallel.ForEach(l.ToArray(), (ip_item) =>
{
try
{
...
}
catch
{
Console.WriteLine(ip_item.IP + " - BAD!");
faileds.Enqueue(ip_item);
}
});
foreach (var item in l.Except(faileds))
{
if (item.AcceptsConnection == true)
{
Console.WriteLine(ip + " Working proxy.");
}
}
And for "all combination", I suggest you list out all combinations first.
var combinations = l.SelectMany(ipItem =>
t.Select(blah2 => Tuple.Create(ipItem, blah2)).ToArray();
foreach (var combination in combinations)
{
var ip = combination.Item1.IP;
var fc = combination.Item2.Split(':');
var u = fc[0];
var p = fc[1];
...
}

Related

How to separate values by ";" in foreach loop for each item using C#

I have a foreach loop iterating each item at a time, I want to separate each item by using ";"
But not adding ";" for the last item.
I have tried using String.Join(";", item), But it did not work for me.
I get the output as : SN-123SN-456SN-789
Output should look something like this: SN-123;SN-456;SN-789
Please find my code below:
if (siteId != "null")
{
var siteList = this.feeDataAccess.GetSitesListById(connectedUser.CurrentEnvironment, siteId);
List<string> siteSNlist = siteList.Gateways.Select(x => x.SerialNumber).ToList();
foreach (var item in siteSNlist)
{
siteSN += String.Join(";", item);
}
}
You need to use string join for a collection, try like this:
if (siteId != "null")
{
var siteList = this.feeDataAccess.GetSitesListById(connectedUser.CurrentEnvironment, siteId);
List<string> siteSNlist = siteList.Gateways.Select(x => x.SerialNumber).ToList();
siteSN = String.Join(";", siteSNlist);
}
For the nested objects you can use select:
if (partnerId != "null")
{
var partnerList = this.feeDataAccess.GetPartnerListbyId(connectedUser.CurrentEnvironment, partnerId);
foreach (var item in partnerList)
{
var partnerSN = string.Join(";", item.Gateways.Select(x => x.SerialNumber));
}
}
String.Join can Concatenates the members of a constructed System.Collections.Generic.IEnumerable`1 collection of type System.String, using the specified separator between each member. So we can use list directly in Join.
List<string> siteSNlist = new List<string>() { "SN-123", "SN-124", "SN-125" , "SN-126"};
string siteSN = string.Join(";", siteSNlist);
Output : SN-123;SN-124;SN-125;SN-126

GROUP BY to List<> with Linq

I'm new to using Linq so I don't understand some things or its syntax. I want to group a list and then loop through it with foreach, like my logic below. Obviously my logic doesn't work.
My code:
var final = finalv.Union(finalc);
final = final.GroupBy(x => x.Clave);
foreach (var articulo in final)
{
Articulo articulo2 = new Articulo();
articulo2.ArtID = articulo.ArtID;
articulo2.Clave = articulo.Clave;
articulo2.ClaveAlterna = articulo.ClaveAlterna;
lista.Add(articulo2);
}
First, such usage is syntactically consistent with this overloaded method of GroupBy: GroupBy<TSource,TKey>(IEnumerable<TSource>, Func<TSource,TKey>), and it will return a IEnumerable<IGrouping<TKey,TSource>> variable.
That means, if you run final.GroupBy(x => x.Clave), let's assume he returns finalWithGrouped, then finalWithGrouped.Key is the key and finalWithGrouped.ToList() is a collection of all variables with the same key(at here, it is with the same Clave).
And for your code, try this:
var final = finalv.Union(finalc);
var finalWithGrouped = final.GroupBy(x => x.Clave);
foreach (var articulosWithSameClavePair in finalWithGrouped)
{
var clave = articulosWithSameClavePair.Key;
var articulos = articulosWithSameClavePair.ToList();
foreach(var articulo in articulos)
{
Articulo articulo2 = new Articulo();
articulo2.ArtID = articulo.ArtID;
articulo2.Clave = articulo.Clave;
articulo2.ClaveAlterna = articulo.ClaveAlterna;
lista.Add(articulo2);
}
}
I suggest you read some examples of using GroupBy.
When you group a list, it will return a key and groued list and you are trying reach a single property of a list.
When you group an data, you can convert it to dictionary, It is not nessesary but better way for me. You can try this code:
var final = finalv.Union(finalc);
final = final.GroupBy(x => x.Clave).ToDictionary(s=> s.Key, s=> s.ToList();
foreach (var articulo in final)
{
foreach (var articuloItem in articulo.value)
{
Articulo articulo2 = new Articulo();
articulo2.ArtID = articuloItem.ArtID;
articulo2.Clave = articuloItem.Clave;
articulo2.ClaveAlterna = articuloItem.ClaveAlterna;
lista.Add(articulo2);
}
}

C# Calculate field inside LINQ Query

I need some help to calculate a property inside my Linq query.
I know I need to use "let" somewhere, but I can't figure it out!
So, first I have this method to get my list from Database:
public BindingList<Builders> GetListBuilders()
{
BindingList<Builders> builderList = new BindingList<Builders>();
var ctx = new IWMJEntities();
var query = (from l in ctx.tblBuilders
select new Builders
{
ID = l.BuilderID,
Projeto = l.NomeProjeto,
Status = l.Status,
DataPedido = l.DataPedido,
DataPendente = l.DataPendente,
DataEntregue = l.DataEntregue,
DataAnulado = l.DataAnulado
});
foreach (var list in query)
builderList.Add(list);
return builderList;
}
Then, I have a function to calculate the Days between Dates accordingly to Status:
public int GetDays()
{
int Dias = 0;
foreach (var record in GetListBuilders)
{
if (record.Status == "Recebido")
{
Dias = GetBusinessDays(record.DataPedido, DateTime.Now);
}
else if (record.Status == "Pendente")
{
Dias = GetBusinessDays(record.DataPedido, (DateTime)record.DataPendente);
}
else if (record.Status == "Entregue")
{
Dias = GetBusinessDays(record.DataPedido, (DateTime)record.DataEntregue);
}
else if (record.Status == "Anulado")
{
Dias = GetBusinessDays(record.DataPedido, (DateTime)record.DataAnulado);
}
}
return Dias;
}
I need to call the GetDays in a DataGridView to give the days for each record.
My big problem is, How do I get this? include it in Linq Query? Calling GetDays() (need to pass the ID from each record to GetDays() function)!?
Any help?
Thanks
I think it would be easier to create an extension method:
public static int GetBusinessDays(this Builders builder) // or type of ctx.tblBuilders if not the same
{
if (builder == null) return 0;
switch(builder.status)
{
case "Recebido": return GetBusinessDays(builder.DataPedido, DateTime.Now);
case "Pendente": return GetBusinessDays(builder.DataPedido, (DateTime)builder.DataPendente);
case "Entregue": return GetBusinessDays(builder.DataPedido, (DateTime)builder.DataEntregue);
case "Anulado": GetBusinessDays(builder.DataPedido, (DateTime)builder.DataAnulado);
default: return 0;
}
}
Then, call it like that:
public BindingList<Builders> GetListBuilders()
{
BindingList<Builders> builderList = new BindingList<Builders>();
var ctx = new IWMJEntities();
var query = (from l in ctx.tblBuilders
select new Builders
{
ID = l.BuilderID,
Projeto = l.NomeProjeto,
Status = l.Status,
DataPedido = l.DataPedido,
DataPendente = l.DataPendente,
DataEntregue = l.DataEntregue,
DataAnulado = l.DataAnulado,
Dias = l.GetBusinessDays()
});
foreach (var list in query)
builderList.Add(list);
return builderList;
}
To do better, to convert a object to a new one, you should create a mapper.
Why does it need to be a part of the query? You can't execute C# code on the database. If you want the calculation to be done at the DB you could create a view.
You're query is executed as soon as the IQueryable is enumerated at the foreach loop. Why not just perform the calculation on each item as they are enumerated and set the property when you are adding each item to the list?

How can I ensure rows are not loaded twice with EF / LINQ

I created code to load definitions from an external API. The code iterates through a list of words, looks up a definition for each and then I thought to use EF to insert these into my SQL Server database.
However if I run this twice it will load the same definitions the second time. Is there a way that I could make it so that EF does not add the row if it already exists?
public IHttpActionResult LoadDefinitions()
{
var words = db.Words
.AsNoTracking()
.ToList();
foreach (var word in words)
{
HttpResponse<string> response = Unirest.get("https://wordsapiv1.p.mashape.com/words/" + word)
.header("X-Mashape-Key", "xxxx")
.header("Accept", "application/json")
.asJson<string>();
RootObject rootObject = JsonConvert.DeserializeObject<RootObject>(response.Body);
var results = rootObject.results;
foreach (var result in results)
{
var definition = new WordDefinition()
{
WordId = word.WordId,
Definition = result.definition
};
db.WordDefinitions.Add(definition);
}
db.SaveChanges();
}
return Ok();
}
Also would appreciate if anyone has any suggestions as to how I could better implement this loading.
foreach (var result in results)
{
if(!(from d in db.WordDefinitions where d.Definition == result.definition select d).Any())
{
var definition = new WordDefinition()
{
WordId = word.WordId,
Definition = result.definition
};
db.WordDefinitions.Add(definition);
}
}
You can search for Definition value.
var wd = db.WordDefinition.FirstOrDefault(x => x.Definition == result.definition);
if(wd == null) {
var definition = new WordDefinition() {
WordId = word.WordId,
Definition = result.definition
};
db.WordDefinitions.Add(definition);
}
In this way you can get a WordDefinition that already have your value.
If you can also use WordId in the same way:
var wd = db.WordDefinition.FirstOrDefault(x => x.WordId == word.WordId);

Which type will return the field method?

I can't work out how to get the Type of a LINQ result. My set contains both strings and bools, so I run into trouble when I try to act on the rows. I attached an incredibly rough workout using try/catch (for a laugh), but it hurts my soul and would much rather know the proper method in obtaining the Type.
private AppointmentInfoClass UpdateDataContext(DataSet phaseDataSet) {
var phaseCollection = new AppointmentInfoClass();
var Type = phaseCollection.GetType();
var properties = Type.GetProperties();
var result = from DataRow myRow in DataBindings.CompanyAppsDataSet.Tables[0].Rows
where (int)myRow["AppointmentID"] == ApptID
select myRow;
var k = 0;
foreach (DataRow row in phaseDataSet.Tables[0].Rows) {
string header;
header = row.Field<string>("Header");
foreach (var field in result) {
try {
properties[k].SetValue(phaseCollection, field.Field<string>(header));
}
catch (Exception) {
properties[k].SetValue(phaseCollection, field.Field<bool>(header).ToString());
}
}
k++;
}
return phaseCollection;
}
It will return the type you have written instead of Type
string s = field.Field<string>("ColumnName");
bool b = field.Field<bool>("ColumnName");

Categories

Resources