Temporary variable inside anonymous type - c#

I have a linq statement similar to the following:
var entities = from row in table.AsEnumerable()
select new
{
ID = row.ID,
X = GetObjectByProcessingID(row.ID)[0],
Y = GetObjectByProcessingID(row.ID)[1],
....
};
Would it be possible to do something like:
var entities = from row in table.AsEnumerable()
select new
{
private var tmp = GetObjectByProcessingID(row.ID),
ID = row.ID,
X = tmp[0],
Y = tmp[1],
....
};
To avoid calling GetObjectByProcessingID twice?
I know you can do something like:
var entities = from row in table.AsEnumerable()
select new
{
ID = row.ID,
XAndY = GetObjectByProcessingID(row.ID),
....
};
But in this case, it will expose the whole array. I also know that I can implement stuff like caching on the method side (GetObjectByProcessingID) or creating a helper method to call it and remember the last value if the ID is the same. But is there a better way? Can I create temporary variables while creating the anonymous type?

Use the let keyword like this:
var entities = from row in table.AsEnumerable()
let tmp = GetObjectByProcessingID(row.ID)
select new {
ID = row.ID,
X = tmp[0],
Y = tmp[1],
....
};
You can also try using method syntax which is very favorite to me:
var entities = table.AsEnumerable()
.Select(row => {
var tmp = GetObjectByProcessingID(row.ID);
return new {
ID = row.ID,
X = tmp[0],
Y = tmp[1],
....
};
});

Related

Get count of same value on table

I have this class where the query must result in this list a property.
This property must check on table how many duplicated exists.
This code works, but its very slow. can you help me ?
var lst = _uow.Repository.GetAll();
var query =
from p in lst
select new GetRfqResponse
{
ID = p.ID,
//bad performance
Count = lst.Where(x => x.Property == p.Property).AsQueryable().Count(),
//
};
Counting in a queryable list can be easily achieved using the Count() function:
// Find duplicated names
var byName = from s in studentList
group s by s.StudentName into g
select new { Name = g.Key, Count = g.Count() };
Check this fiddle to see it running.
Below is for InMemory
GroupBy should come to help.
var propertyGroupedList = list.GroupBy(l=>l.Property);
var query = list.Select(l => new GetRfqResponse{
Id = l.Id,
Count = propertyGroupedList.First(g=> g.Key == l.Property).Count()
});
Or you can create a dictionary with key as "Property" and value as count, then you will have to loop just once to store the count.
This allows you to get count in constant time
Dictionary<string, int> map = new Dictionary<string, int>();
foreach (var item in lst)
{
if (!map.ContainsKey(lst.Property))
{
map.Add(item.Property, 1);
}
else
map[item.Property]++;
}
var z = lst.Select(l => new GetRfqResponse{
Id = l.ID,
Count = map[l.Property]
});

convert SQL to LINQ or imporve my query please

I am trying to convert sql to lambda or LINQ but can't simplified yet,
I managed to do it two different lambda but i want it a single query.
SQL query is this :
SELECT PamID, MAX (MaxAmount)
FROM RebateTable
GROUP BY PamID
so far this is working but is there any better way.
var t = from r in RebateList
group r by r.PamID;
var x = from y in t
select new RebateMaxClass
{
PamId = y.Key,
TotalSale = y.Max(s => s.MaxAmount)
};
You could use this form:
RebateTable.GroupBy(r=>r.PamId).Select(s=>new RebateMaxClass
{
PamId = s.Key,
TotalSale = s.Max(y => y.MaxAmount)
};
The query look good. You could form a single query like this:
var t = from r in RebateList
group r by r.PamId into y
select new
{
PamId = y.Key,
TotalSale = y.Max(s => s.MaxAmount)
};
But this is not faster. The Query is extended and will ont be executed until is has to.
An alternative is forming the "new LinQ-Style":
var t2 = RebateList.GroupBy(g => g.PamId) // Do a Grouping
var t3 = t2.Select(s => new { PamId = s.Key, TotalSale = s.Max(m => m.MaxAmount) });

Store List of objects in Session variable

I want to store the result of the query called by the controller in a variable
public ActionResult Index()
{
Session["dateDebut"] = DateTime.Now.AddMonths(-1).ToString("dd/MM/yyyy", CultureInfo.InvariantCulture);
Session["dateFin"] = DateTime.Now.AddDays(0).ToString("dd/MM/yyyy", CultureInfo.InvariantCulture);
HostClassReq hostClassChart = new HostClassReq();
Chart_Event cex = new Chart_Event();
var viewModel = new Chart_Event
{
chartVM = hostClassChart.callHostClass()
};
return View(viewModel);
}
Here is the methode callHostClass implementation
public Highcharts callHostClass()
{
DateTime begin = DateTime.ParseExact(HttpContext.Current.Session["dateDebut"].ToString(), "dd/MM/yyyy",
System.Globalization.CultureInfo.InvariantCulture);
DateTime end = DateTime.ParseExact(HttpContext.Current.Session["dateFin"].ToString(), "dd/MM/yyyy",
System.Globalization.CultureInfo.InvariantCulture).AddDays(1);
CreateChart createChart = new CreateChart();
List<String> xs = new List<string>();
var maListe = (from p in db.exclure
where (p.type.Contains("Host Class"))
group p by p.libelle into g
select new
{
libellex = g.Key
}).ToList();
List<string> strListe = new List<string>();
foreach (var x in maListe.Select(i => i.libellex))
{
strListe.Add(x.ToString());
}
var myList = (from p in db.Full
where ( (p.date_reception > begin & p.date_reception < end & !p.mc_host_class.Contains("NULL")) &
(!strListe.Contains(p.mc_host_class)))
group p by p.mc_host_class into g
orderby g.Count() descending
select new
{
hostclassx = g.Key,
countx = g.Count()
}).Take(10).ToList();
// HttpContext.Current.Session["allList"] = myList;
List<Full> questions = (List<Full>)HttpContext.Current.Session["allList"];
// questions = List <Full> myList;
foreach (var x in questions)
{
}
object[] ys = myList.Select(a => (object)a.countx.ToString()).ToArray();
foreach (var x in myList.Select(i => i.hostclassx))
{
if (x.Length > 20)
{
xs.Add((x.Substring(0, 20)));
}
else
{
xs.Add(x);
}
}
var chart = createChart.createChartBar(xs, ys, 10);
return chart;
}
I need to store the result of myList query in a variable that will be accessed by another classes i need some help.
Are you looking for this?
Session["yourName"]=myList;
EDIT After question edit emerged that he wanted to use session in a class not extending Controller.
NEW PART
Therefore you can't use the initial suggestion but instead include System.Web using System.Web; and use
HttpContext.Current.Session["yourName"]=myList;
When you have to get it you use
var yourList = (myListType)Session["yourName"];
if you are in a class extending Controller or
var yourList = (myListType)HttpContext.Current.Session["yourName"];
otherwise.
Try this:
HttpContext.Current.Session["name"] = mylist;
But be careful accessing session like that, might cause null-ref exceptions

Selecting multiple columns from each row and removing duplicates

Say I have a table with the following structure:
- Id
- Phone1
- Phone2
- Address
This table has multiple records.
What's the best way, using linq to SQL, of selecting all the phone numbers (from columns "Phone1" and "Phone2") in each row, and also removing repeated values.
I've tried something like but I can only get one column (Phone1) in each row:
var listOfResults = (from x in table
select x.Select(z => z.Phone1).Distinct()
).ToList();
Many thanks!
You can do this:
var listOfResults = (from x in table
select new
{
Phone1 = x.Phone1,
Phone2 = x.Phone2
}).Distinct();
or use groupby:
var listOfResults = (from x in table
group x by new { x.Phone1,x.Phone2 } into g
select new
{
Phone1 = g.Key.Phone1,
Phone2 = g.Key.Phone2
});
UPDATE:
var listOfResults = (from x in table
select new[]
{
new { Phone = x.Phone1 },
new { Phone = x.Phone2}
}).SelectMany(x=>x).Distinct();
var listOfPhone1 = (from x in table select x.Select(z => z.Phone1);
var listOfPhone2 = (from x in table select x.Select(z => z.Phone2);
var listOfResults = (listOfPhone1.AddRange(listOfPhone2)).Distinct();
You could have a look at the MoreLinq library found here. They have a function called DistinctBy which should solve your problem.
I don't know if this works with Linq-to-SQL, but with Linq-to-Object I would do it this way:
var unified = addresses.SelectMany(Row => new[] { new { Row, Phone = Row.Phone1 }, new { Row, Phone = Row.Phone2 } })
.Distinct(entry => entry.Phone)
.Select(entry => entry.Row);

Ordinal Position of Element in IENumerable Collection (Linq to XMl )

How do I embed the ordinal number of element as its attribute in this linq query.
var AllSections = from s in xmlDoc.Descendants("section")
select new
{
id = s.Attribute("id").Value,
themeTitle = s.Element("themeTitle").Value,
themeText = s.Element("themeText").Value,
objects = (from a in AllObjects
join b in s.Descendants("object")
on a.Attribute("accessionNumber").Value equals
b.Attribute("accessionNumber").Value
//select a
select new
{
//index = insert ordinal id/index of element
ObjectTitle = a.Element("ObjectTitle").Value,
ObjectText = a.Element("textentry").Value,
}
)
};
You can't easily do it with a query expression - at least not without a horrible side effect. However, you can easily do it with dot notation for either Select or Where. Given that you've got quite a long query expression, it's probably easiest to embed an extra call to where at the start - assuming you do actually want the index of "s" in the original expression:
var AllSections =
from s in xmlDoc.Descendants("section")
select new
{
id = s.Attribute("id").Value,
themeTitle = s.Element("themeTitle").Value,
themeText = s.Element("themeText").Value,
objects = (from a in AllObjects.Select((Item,Index) => new {Item,Index})
join b in s.Item.Descendants("object")
on a.Item.Attribute("accessionNumber").Value equals
b.Attribute("accessionNumber").Value
//select a
select new
{
//index = insert ordinal id/index of element
Index = a.Index,
ObjectTitle = a.Element("ObjectTitle").Value,
ObjectText = a.Element("textentry").Value,
}
)
};
That's assuming you want the index of a within AllObjects.
#Jon Skeet gave you the appropriate overload of Select to use, and here is it in your query:
var AllSections = from s in xmlDoc.Descendants("section")
select new
{
id = s.Attribute("id").Value,
themeTitle = s.Element("themeTitle").Value,
themeText = s.Element("themeText").Value,
objects = (from a in AllObjects
join b in s.Descendants("object")
on a.Attribute("accessionNumber").Value
equals b.Attribute("accessionNumber").Value
select a).Select((a, index) =>
new
{
Index = index,
ObjectTitle = a.Element("ObjectTitle").Value,
ObjectText = a.Element("textentry").Value,
})
};

Categories

Resources