LINQ Query Error - where clause in foreach loop - c#

I wrote a LINQ query but I have some problem in executing where clause in foreach loop.
using (DataClasses1DataContext db = new DataClasses1DataContext(("ConnectionString")))
{
Table<NOTIF_SCHED> NOTIF_SCHED_alias = db.GetTable<NOTIF_SCHED>();
IQueryable<NOTIF_SCHED> notif_sched_data = from sched in NOTIF_SCHED_alias select sched;
foreach (var notif_sched_data_value in notif_sched_data)
{
string a = notif_sched_data_value.NOTIF_RPT_ID.ToString();
Table<mainframe_replication> mainframe_replications_alias = db.GetTable<mainframe_replication>();
IQueryable<mainframe_replication> mainframe_replications_data =
from mfrepl in mainframe_replications_alias
where (mfrepl.RPT_ID.Equals(a))
select mfrepl;
foreach (var mainframe_replication_data_value in mainframe_replications_data)
{
Console.WriteLine("hi");
}
}
}
I am not able to use Where clause in line:
IQueryable<mainframe_replication> mainframe_replications_data =
from mfrepl in mainframe_replications_alias
where (mfrepl.RPT_ID.Equals(a))
select mfrepl;**
Can someone please help and check if the syntax is wrong.

This should do the same thing and run much faster:
using (DataClasses1DataContext db = new DataClasses1DataContext(("ConnectionString")))
{
var ids = db.NOTIF_SCHEDs.Select(x=>x.NOTIF_RPT_ID).ToArray();
var repl = db.mainframe_replication
.Where(mfrepl=>ids.Contains(mfrepl.RPT_ID));
foreach (var mainframe_replication_data_value in repl)
{
Console.WriteLine("hi");
}
}
}
If NOTIF_RPT_ID is not a string, and RPT_ID is, you can do this:
using (DataClasses1DataContext db = new DataClasses1DataContext(("ConnectionString")))
{
var ids = db.NOTIF_SCHEDs.Select(x=>x.NOTIF_RPT_ID.ToString()).ToArray();
var repl = db.mainframe_replication
.Where(mfrepl=>ids.Contains(mfrepl.RPT_ID));
foreach (var mainframe_replication_data_value in repl)
{
Console.WriteLine("hi");
}
}
}

Related

Reading DataCollection<Entity> from Dynamics CRM using C#

I am trying to pull and read the entity from Dynamics CRM using C#. I am using retrieveMultiple method and all I am getting is Microsoft.Xrm.Sdk.OptionSetValue. When I debug I see 1000 records but every record is showing the same text Microsoft.Xrm.Sdk.OptionSetValue. What am I doing wrong here?
QueryExpression bookQuery = new QueryExpression("new_res")
{
ColumnSet = new ColumnSet("new_book"),
Criteria =
{
Conditions =
{
new ConditionExpression()
{
AttributeName="new_bookid",
Operator = ConditionOperator.NotNull
}
}
}
};
DataCollection<Entity> bookList = service.RetrieveMultiple(bookeQuery).Entities;
foreach (var c in bookList)
{
Console.WriteLine(c.Attributes["new_bookid"]);
}
I just needed to use an EntityCollection:
EntityCollection bookList = (EntityCollection)service.RetrieveMultiple(bookQuery);
if (bookList.Entities.Count > 0)
{
var record = bookList.Entities[0];
var recordNumberString = string.Empty;
}

How to combine a distinct query with projection with C# MongoDB driver

I try to combine a projection and a distinct with the MongoDB driver but don't get anywhere...
I have:
var coll = db.GetCollection<Vat>(CommonConstants.VatCodeCollection);
// I like to combine in one statement:
var result = coll.Distinct<DateTime>("ValidSince", filter).ToList();
var projection = Builders<Vat>.Projection.Expression(x => new VatPeriod { ValidSince = x.ValidSince });
So at the end I like to get a List<VatPeriod> as a result of one statement. Of course I could do something like
var coll = db.GetCollection<Vat>(CommonConstants.VatCodeCollection);
List<VatPeriod> vatPeriods = null;
try
{
var result = coll.Distinct<DateTime>("ValidSince", filter).ToList();
if (result.Count > 0)
{
vatPeriods = new List<VatPeriod>(result.Count);
foreach (var dateTime in result)
{
vatPeriods.Add(new VatPeriod() {ValidSince = dateTime});
}
}
return vatPeriods;
}
catch .....
in my repository class, but I would prefer to do everything on the Mongo server. Any idea if and how this is possible?

Pass query result to method (Linq, Wpf)

I have method to save all values from table to txt file:
UserDataDBsDataContext dataContext = new UserDataDBsDataContext();
List<UserData> usersL = (from u in dataContext.UserDatas
select u).ToList();
var properties = typeof(UserData).GetProperties();
var userValues = new List<string>();
foreach (var user in usersL)
{
var values = new List<object>();
foreach (var property in properties)
{
object value = property.GetValue(user, null);
values.Add(value);
}
userValues.Add(string.Join(",", values));
}
File.WriteAllLines("my_data.txt", userValues);
Now I have two query and I want to do exactly the same, so I tried to create separate method responsible for looping table values.
Loop Method:
public void loopProp(PropertyInfo[] properites, List<string> addedValues)
{
foreach (var qrl in ...........)
{
var values = new List<object>();
foreach (var property in properites)
{
object value = property.GetValue(qrl, null);
values.Add(value);
}
addedValues.Add(string.Join(",", values));
}
File.WriteAllLines("my_passed_data.txt", addedValues);
}
But I don't know, how to pass query result(ar or ud):
My code:
List<AutoRef> ar = (from a in rjdc.AutoRefs
select a).ToList();
List<UserDataRef> ud = (from u in rjdc.UserDataRefs
select u).ToList();
var propertiesAutoRef = typeof(AutoRef).GetProperties();
var autoValues = new List<string>();
var propertiesUserRef = typeof(UserDataRef).GetProperties();
var userValues = new List<string>();
//loopProp(propertiesAutoRef, autoValues);
//loopProp(propertiesUserRef, userValues);
Answering your concrete question. You should make the method generic and pass the source as IEnumerable<T>:
public void loopProp<T>(IEnumerable<T> source, PropertyInfo[] properites, List<string> addedValues)
{
foreach (var qrl in source)
{
// ...
}
File.WriteAllLines("my_passed_data.txt", addedValues);
}
Usage:
loopProp(ar, propertiesAutoRef, autoValues);
loopProp(ud, propertiesUserRef, userValues);
Probably you should pass the file path argument as well instead of hardcoding it inside the method.

Stepping out of foreach after finding right productID

Each of our products are based on a certain categoryID
When looping through our products it has to first find the product within that category (which it does) and then step out of it. The problem is that when it has gone through the foreach the first time (finding the right prouducts) it does not step out, it just keeps going through it finding the remainding products with other categoryIDs.
How do we solve this?
(We are using C# - Entity Framework - MSSQL)
CHEERS!
public ActionResult Index(int id)
{
var m = new Models.Product.Index();
//m.DisplayName = "Produkter";
//var scp = db.SCPconnection.FirstOrDefault(s => s.CategoryID == id);
//if (id == scp.ProductID)
{
foreach (var item in db.Product.OrderBy(p => p.ProductName))
{
var mp = new Models.Product.ModelProduct();
mp.SectorName = item.ProductName;
mp.ProductID = item.ProductID;
mp.DetailsUrl = item.Details;
m.AllProducts.Add(mp);
}
}
return View(m);
}
Just break it.
foreach (var item in db.Product.OrderBy(p => p.ProductName))
{
var mp = new Models.Product.ModelProduct();
mp.SectorName = item.ProductName;
mp.ProductID = item.ProductID;
mp.DetailsUrl = item.Details;
m.AllProducts.Add(mp);
if(condition) //if it is needed
break;
}
It is better to filter using Where clause for a particular ID.
I would strongly suggest Optimized code, why would you require to get all Products details to business logic, instead query for what is needed with a condition.
foreach (var item in db.Product.Where(p => p.ProductID.Equals(requiredID)).OrderBy(p => p.ProductName))
{
var mp = new Models.Product.ModelProduct();
mp.SectorName = item.ProductName;
mp.ProductID = item.ProductID;
mp.DetailsUrl = item.Details;
m.AllProducts.Add(mp);
}
The break keyword immediately exits the foreach at that point. Code after the break and remaining iteration items will NOT be processed.
public ActionResult Index(int id)
{
var m = new Models.Product.Index();
foreach (var item in db.Product.OrderBy(p => p.ProductName))
{
var mp = new Models.Product.ModelProduct();
mp.SectorName = item.ProductName;
mp.ProductID = item.ProductID;
mp.DetailsUrl = item.Details;
m.AllProducts.Add(mp);
if (item.ProductID == id)
break;
}
}
return View(m);
}

How can I write a LINQ to SQL query to update tags?

I have an image site where users can tag photos much like you can tag a question on Stackoverflow.
I have the following tables:
Images [ID, URL, etc]
Tags [ID, TagName]
ImageTag [TagID, ImageID]
I want to write a method with the signature:
public void UpdateImageTags(int imageId, IEnumerable<string> currentTags)
This method will do the following:
Create any new Tags in currentTags that don't already exist in the Tags table.
Get the old ImageTag's for an image.
Delete any ImageTag's that no longer exist in the currentTags
Add any ImageTag's that are new between the currentTags and oldTags.
Here is my attempt at that method:
public void UpdateImageTags(int imageId, IEnumerable<string> currentTags)
{
using (var db = new ImagesDataContext())
{
var oldTags = db.ImageTags.Where(it => it.ImageId == imageId).Select(it => it.Tag.TagName);
var added = currentTags.Except(oldTags);
var removed = oldTags.Except(currentTags);
// Add any new tags that need created
foreach (var tag in added)
{
if (!db.Tags.Any(t => t.TagName == tag))
{
db.Tags.InsertOnSubmit(new Tag { TagName = tag });
}
}
db.SubmitChanges();
// Delete any ImageTags that need deleted.
var deletedImageTags = db.ImageTags.Where(it => removed.Contains(it.Tag.TagName));
db.ImageTags.DeleteAllOnSubmit(deletedImageTags);
// Add any ImageTags that need added.
var addedImageTags = db.Tags.Where(t => added.Contains(t.TagName)).Select(t => new ImageTag { ImageId = imageId, TagId = t.TagId });
db.ImageTags.InsertAllOnSubmit(addedImageTags);
db.SubmitChanges();
}
}
However, this fails on the line:
db.ImageTags.DeleteAllOnSubmit(deletedImageTags);
With the error:
Local sequence cannot be used in LINQ to SQL implementations of query
operators except the Contains operator.
Is there an easier way I can handle the operation of adding new tags, deleting old ImageTags, adding new ImageTags in LINQ to SQL?
Seems like this would be easiest
public void UpdateImageTags(int imageId, IEnumerable<string> currentTags)
{
using (var db = new ImagesDataContext())
{
var image = db.Images.Where(it => it.ImageId == imageId).First()
image.Tags.Clear();
foreach(string s in currentTags)
{
image.Tags.Add(new Tag() { TagName = s});
}
db.SubmitChanges();
}
}
This might have to be modified slightly for LinqtoSQL. EF is what i have been using most recently. Also this is dependent on Lazy loading being enabled. If it is not, you will have to force the include of the image tags.
Here is a helper method to deal with many-to-many relationships:
public static void UpdateReferences<FK, FKV>(
this EntitySet<FK> refs,
Expression<Func<FK, FKV>> fkexpr,
IEnumerable<FKV> values)
where FK : class
where FKV : class
{
Func<FK, FKV> fkvalue = fkexpr.Compile();
var fkmaker = MakeMaker(fkexpr);
var fkdelete = MakeDeleter(fkexpr);
var fks = refs.Select(fkvalue).ToList();
var added = values.Except(fks);
var removed = fks.Except(values);
foreach (var add in added)
{
refs.Add(fkmaker(add));
}
foreach (var r in removed)
{
var res = refs.Single(x => fkvalue(x) == r);
refs.Remove(res);
fkdelete(res);
}
}
static Func<FKV, FK> MakeMaker<FKV, FK>(Expression<Func<FK, FKV>> fkexpr)
{
var me = fkexpr.Body as MemberExpression;
var par = Expression.Parameter(typeof(FKV), "fkv");
var maker = Expression.Lambda(
Expression.MemberInit(Expression.New(typeof(FK)),
Expression.Bind(me.Member, par)), par);
var cmaker = maker.Compile() as Func<FKV, FK>;
return cmaker;
}
static Action<FK> MakeDeleter<FK, FKV>(Expression<Func<FK, FKV>> fkexpr)
{
var me = fkexpr.Body as MemberExpression;
var pi = me.Member as PropertyInfo;
var assoc = Attribute.GetCustomAttribute(pi, typeof(AssociationAttribute))
as AssociationAttribute;
if (assoc == null || !assoc.DeleteOnNull)
{
throw new ArgumentException("DeleteOnNull must be set to true");
}
var par = Expression.Parameter(typeof(FK), "fk");
var maker = Expression.Lambda(
Expression.Call(par, pi.GetSetMethod(),
Expression.Convert(Expression.Constant(null), typeof(FKV))), par);
var cmaker = maker.Compile() as Action<FK>;
return cmaker;
}
Usage:
IEnumerable<Tag> values = ...;
Image e = ...;
e.ImageTags.UpdateReferences(x => x.Tag, tags);

Categories