How to return Entity Data along with related Entities - mysql

Here is the structure:
And below is the code:
public IQueryable<PageTemplate> GetTemplate()
{
var PageTemplates = from oPT in _db.PageTemplates
join oHSFK in _db.HelperSites on oPT.SiteID equals oHSFK.SiteID into oHSChild
from oHS in oHSChild.DefaultIfEmpty()
join oHUFK in _db.HelperUsers on oPT.SiteID equals oHUFK.UserID into oHUChild
from oHU in oHUChild.DefaultIfEmpty()
where oPT.SiteID == ConfigDto.SiteDetails.SiteID || oPT.SiteID == null
select new
{
TemplateID = oPT.TemplateID,
TemplateName = oPT.TemplateName,
//SiteName = oHS.SiteName,
//UpdatedByName = oHU.UserFirstName + " " + oHU.UserLastName,
UpdatedDate = oPT.UpdatedDate
};
return null;
}
How do I return IQueryable<PageTemplate> which has related Entities already. I know the workaround of making a new class having all the required properties of PageTemplate, HelperSite & HelperUser classes. But, I am looking for a solution, if possible, to use existing Entity Framework classes.

Related

How do I consume a JSon object that has no headers?

My C# MVC5 Razor page returns a Newtonsoft json link object to my controller (the "1" before \nEdit |" indicates that the checkbox is checked:
"{\"0\": [\"6146\",\"Kimball\",\"Jimmy\",\"General Funny Guy\",\"277\",\"Unite\",\"Jun 2019\",\"\",\"\",\"1\",\"\nEdit |\nDetails\n\n \n\"],\"1\": [\"6147\",\"Hawk\",\"Jack\",\"\",\"547\",\"Painters\",\"Jun 2019\",\"\",\"\",\"on\",\"\nEdit |\nDetails\n\n \n\"]}"
How do I parse this?
I am using a WebGrid to view and I want to allow the users to update only the lines they want (by checking the checkbox for that row), but it doesn't include an id for the 's in the dom. I figured out how to pull the values, but not the fieldname: "Last Name" , value: "Smith"... I only have the value and can't seem to parse it... one of my many failed attempts:
public ActoinResult AttMods(string gridData)
{
dynamic parsedArray = JsonConvert.DeserializeObject(gridData);
foreach (var item in parsedArray)
{
string[] itemvalue = item.Split(delimiterChars);
{
var id = itemvalue[0];
}
}
I finally sorted this one out..If there is a more dynamic answer, please share... I'll give it a few days before I accept my own (admittedly clugy) answer.
if(ModelState.IsValid)
{
try
{
Dictionary <string,string[]> log = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string[]>>(gridData);
foreach (KeyValuePair<string,string[]> keyValue in log)
{
if (keyValue.Value[9] == "1")//Update this row based on the checkbox being checked
{
var AttendeeID = keyValue.Value[0];
int intAttendeeID = 0;
if (int.TryParse(AttendeeID, out intAttendeeID))//Make sure the AttendeeID is valid
{
var LName = keyValue.Value[1];
var FName = keyValue.Value[2];
var Title = keyValue.Value[3];
var kOrgID = keyValue.Value[4];
var Org = keyValue.Value[5];
var City = keyValue.Value[7];
var State = keyValue.Value[8];
var LegalApproval = keyValue.Value[9];
tblAttendee att = db.tblAttendees.Find(Convert.ToInt32(AttendeeID));
att.FName = FName;
att.LName = LName;
att.Title = Title;
att.kOrgID = Convert.ToInt32(kOrgID);
att.Organization = Org;
att.City = City;
att.State = State;
att.LegalApprovedAtt = Convert.ToBoolean(LegalApproval);
}
}
}
db.SaveChanges();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
You can avoid assigning the var's and just populate the att object with the KeyValue.Value[n] value, but you get the idea.

How to insert a Path in between an existing Path

I am working on an implementation to generate alternate Paths using via node method.
While checking for local optimality I do the following
forwardEdge = bestWeightMapFrom.get(viaNode);
reverseEdge = bestWeightMapTo.get(viaNode);
double unpackedUntilDistance = 0;
while(forwardEdge.edge != -1) {
double parentDist = forwardEdge.parent != null ? forwardEdge.parent.distance : 0;
double dist = forwardEdge.distance - parentDist;
if(unpackedUntilDistance + dist >= T_THRESHOLD) {
EdgeSkipIterState edgeState = (EdgeSkipIterState) graph.getEdgeProps(forwardEdge.edge, forwardEdge.adjNode);
unpackStack.add(new EdgePair(edgeState, false));
sV = forwardEdge.adjNode;
forwardEdge = forwardEdge.parent;
break;
}
else {
unpackedUntilDistance += dist;
forwardEdge = forwardEdge.parent;
sV = forwardEdge.adjNode;
}
}
int oldSV = forwardEdge.adjNode;
EdgeEntry oldForwardEdge = forwardEdge;
I unpack the edge in the stack to further narrow down sV.
I get vT and oldVt in a similar fashion by traversing reverseEdge.
if I determine that the path from sV and vT is <= length of unpacked edges I accept this via node and construct the alternatePath as follows.
PathBidirRef p = (PathBidirRef) algo.calcPath(oldSV, oldVT);
Path4CHAlt p1 = new Path4CHAlt(graph, flagEncoder);
p1.setSwitchToFrom(false);
p1.setEdgeEntry(oldForwardEdge);
p1.segmentEdgeEntry = p.edgeEntry;
double weight = oldForwardEdge.weight + oldReverseEdge.weight + p.edgeEntry.weight + p.edgeTo.weight;
p1.setWeight(weight);
p1.edgeTo = oldReverseEdge;
p1.segmentEdgeTo = p.edgeTo;
Path p2 = p1.extract();
Path4CHAlt is
public class Path4CHAlt extends Path4CH {
private boolean switchWrapper = false;
public EdgeEntry segmentEdgeTo;
public EdgeEntry segmentEdgeEntry;
public Path4CHAlt( Graph g, FlagEncoder encoder )
{
super(g, encoder);
}
public Path4CHAlt setSwitchToFrom( boolean b )
{
switchWrapper = b;
return this;
}
#Override
public Path extract()
{
System.out.println("Path4CHAlt extract");
if (edgeEntry == null || edgeTo == null || segmentEdgeEntry == null || segmentEdgeTo == null)
return this;
if (switchWrapper)
{
EdgeEntry ee = edgeEntry;
edgeEntry = edgeTo;
edgeTo = ee;
ee = segmentEdgeEntry;
segmentEdgeEntry = segmentEdgeTo;
segmentEdgeTo = ee;
}
EdgeEntry currEdge = segmentEdgeEntry;
while (EdgeIterator.Edge.isValid(currEdge.edge))
{
processEdge(currEdge.edge, currEdge.adjNode);
currEdge = currEdge.parent;
}
currEdge.parent = edgeEntry;
currEdge = edgeEntry;
while (EdgeIterator.Edge.isValid(currEdge.edge))
{
processEdge(currEdge.edge, currEdge.adjNode);
currEdge = currEdge.parent;
}
setFromNode(currEdge.adjNode);
reverseOrder();
currEdge = segmentEdgeTo;
int tmpEdge = currEdge.edge;
while (EdgeIterator.Edge.isValid(tmpEdge))
{
currEdge = currEdge.parent;
processEdge(tmpEdge, currEdge.adjNode);
tmpEdge = currEdge.edge;
}
currEdge.parent = edgeTo;
currEdge = edgeTo;
tmpEdge = currEdge.edge;
while (EdgeIterator.Edge.isValid(tmpEdge))
{
currEdge = currEdge.parent;
processEdge(tmpEdge, currEdge.adjNode);
tmpEdge = currEdge.edge;
}
setEndNode(currEdge.adjNode);
return setFound(true);
}
}
This is not working all the time. I get exceptions in Path4CH
java.lang.NullPointerException
at com.graphhopper.routing.ch.Path4CH.expandEdge(Path4CH.java:62)
at com.graphhopper.routing.ch.Path4CH.processEdge(Path4CH.java:56)
at com.graphhopper.routing.PathBidirRef.extract(PathBidirRef.java:95)
at com.graphhopper.routing.DijkstraBidirectionRef.extractPath(DijkstraBidirectionRef.java:99)
at com.graphhopper.routing.AbstractBidirAlgo.runAlgo(AbstractBidirAlgo.java:74)
at com.graphhopper.routing.AbstractBidirAlgo.calcPath(AbstractBidirAlgo.java:60)
In Path
java.lang.IllegalStateException: Edge 1506012 was empty when requested with node 1289685, array index:0, edges:318
at com.graphhopper.routing.Path.forEveryEdge(Path.java:253)
at com.graphhopper.routing.Path.calcInstructions(Path.java:349)
I dont know what I am doing wrong. I could really use some help with this.
Thanks.
I solved this issue.
Inside DijkstraBidirectionRef.calcPath I was trying to calculate shortest path from an arbitrary node to source node and vertex node.
The error used to occur because the original call to calcPath was operating on QueryGraph and inside I was creating a new Object of DijkstraBidirectionRef using LevelGraphStorage.
This was a problem because QueryGraph may create virtual nodes and edges for source and target nodes. Call to calcPath(node, virtualNode) operating on LevelGraphStorage would throw an exception.
The fix was to call algo.setGraph(queryGraph) after creating DijkstraBidirectionRef.

Vici coolstorage bug in saving ManyToMany pure relations?

We have a test case that creates a many-many relation between entities X and Y and then deletes the same relation.
SQLite throws a constraint violation that the relation exists. After digging a bit, we found that the relationship table still has an entry for the relationship.
It appears that this may be a bug in Vici CoolStorage itself. The code that handles removed and added objects looks like this (in CSListGeneric.cs):
if (Relation != null && Relation.PureManyToMany)
{
if (_removedObjects != null)
{
foreach (TObjectType obj in _removedObjects)
{
CSParameterCollection parameters = new CSParameterCollection();
parameters.Add("#LocalKey").Value = RelationObject.Data["#" + Relation.LocalKey].Value;
parameters.Add("#ForeignKey").Value = obj.Data["#" + Relation.ForeignKey].Value;
string deleteSql = DB.BuildDeleteSQL(Relation.LinkTable, null, DB.QuoteField(Relation.LocalLinkKey) + "=#LocalKey and " + DB.QuoteField(Relation.ForeignLinkKey) + "=#ForeignKey");
DB.ExecuteNonQuery(deleteSql, parameters);
}
_removedObjects = null;
}
if (_addedObjects != null)
{
foreach (TObjectType obj in _addedObjects)
{
CSParameterCollection parameters = new CSParameterCollection();
parameters.Add("#LocalKey").Value = RelationObject.Data["#" + Relation.LocalKey].Value;
parameters.Add("#ForeignKey").Value = obj.Data["#" + Relation.ForeignKey].Value;
DB.ExecuteInsert(Relation.LinkTable,
new[] { Relation.LocalLinkKey, Relation.ForeignLinkKey },
new[] { "#LocalKey", "#ForeignKey" },
null, null, null, parameters);
}
_addedObjects = null; // THIS WAS ADDED TO FIX THE BUG
}
Note that the removed objects collection is set to null after the delete statements are executed. However, the added objects collection is not similarly reset.
Adding the line at the bottom appears to fix the issue.
Is this the correct fix, or are we missing something?

Parse a string value using mysql

I have a value in a column in this manner
"id=Clarizen,ou=GROUP,dc=opensso,dc=java,dc=net|id=devendrat,ou=USER,dc=opensso,dc=java,dc=net"
I want to extract group name and user name from this string and will store it into separate columns of another table.
Desired result:
Clarizen as Groupname
devendrat as Username
Please help
You are looking for CharIndex and Substring option.
The following works for T-SQL. I am not sure about the Syntax in My SQL
SELECT REPLACE(SUBSTRING(ColumnName,1,CHARINDEX(',',ColumnName) - 1),'ID=','')
AS Groupname,
REPLACE(SUBSTRING(SUBSTRING(ColumnName,CHARINDEX('|',ColumnName),
LEN(ColumnName)),1,
CHARINDEX(',',ColumnName) - 1),'|ID=','') AS Username
(sorry this is C# I overlooked that you are using mysql, so the answer is useless to you but I'll leave it here unless someone is to remove it)
Using string split can get the job done, here is something that I whipped together, it won't be optimal but it definately works!
string parse_me = "id=Clarizen,ou=GROUP,dc=opensso,dc=java,dc=net|id=devendrat,ou=USER,dc=opensso,dc=java,dc=net";
string[] lines = parse_me.Split(',');
List<string> variables = new List<string>();
List<string> values = new List<string>();
foreach (string line in lines)
{
string[] pair = line.Split('=');
//Console.WriteLine(line);
variables.Add(pair[0]);
values.Add(pair[1]);
}
string group = "";
string user = "";
if (variables.Count == values.Count)
{
for (int i = 0; i < variables.Count; ++i )
{
Console.Write(variables[i]);
Console.Write(" : ");
Console.WriteLine(values[i]);
if (variables[i] == "ou")
{
if (group == "")
{
group = values[i];
}
else if (user == "")
{
user = values[i];
}
}
}
}
Console.WriteLine("Group is: " + group);
Console.WriteLine("User is: " + user);
Console.ReadLine();

Local sequence cannot be used in LINQ to SQL implementation

I'm getting an error, see below, when I try to generate a list of the class MappedItem. In short the code example below tries to find products by category, date range and SKU. The requirement I have is that the user should be able to enter a comma separated list of SKUs and the search is to find any product whos SKU starts with one of the SKUs entered by the user. When I run the code, I get.
Local sequence cannot be used in LINQ to SQL implementation of query operators except the Contains() operator.
The abbreviated sequence is this:
Convert the comma separated string of SKUs into a list of strings.
string sku = TextSKU.Text;
List<string> skuList = sku.Split(new char[] { ',' }).ToList();
Define elsewhere in the code the class that will accept the search results.
public class MappedItem
{
public string ItemDescription { get; set; }
public int ItemCount { get; set; }
public MappedItem()
{
}
public MappedItem(string itemDescription, int itemCount)
{
ItemDescription = itemDescription;
ItemCount = itemCount;
}
}
Here's the query that I generate my results from
List<MappedItem> widgetItems = (from c1 in db.CCRCodes
join pac in db.widgetAssignedCodes on c1.code_id equals pac.code_id
join ph in db.widgetHistories on pac.history_id equals ph.history_id
where ph.contact_dt.Value.Date >= startDate && ph.contact_dt.Value.Date <= endDate &&
(string.IsNullOrEmpty(baanCatFam) || ph.baan_cat_family_code == baanCatFam) &&
(string.IsNullOrEmpty(baanCat) || ph.baan_cat_code == baanCat) &&
(string.IsNullOrEmpty(baanSubCat) || (ph.baan_sub_cat_code == baanSubCat)) &&
(string.IsNullOrEmpty(sku) || skuList.All(sl => ph.product_mod.StartsWith(sl)))
group c1 by c1.code_desc into ct
select new MappedItem
{
ItemDescription = ct.Key.ToUpper(),
ItemCount = ct.Count()
}).OrderByDescending(m => m.ItemCount)
.ToList();
I believe that the culprit is the line of code that I've extracted and displayed below.
skuList.All(sl => ph.product_mod.StartsWith(sl))
This identifies all skus that start with an element from the skuList which is derived from a comma delimited lists of skus entered by the user. My question is, what causes this error, and given the code examples, what do I do to get around them.
First - logically you want Any, not All.
Second, this is a poor way to build up a query filter. All of those operations are sent into the database, while the information to determine which filters should be applied is already local. The explicit joins are also bad (association properties could be used instead).
IQueryable<WidgetHistory> query = db.widgetHistories
.Where(ph => ph.contact_dt.Value.Date >= startDate
&& ph.contact_dt.Value.Date <= endDate);
if (!string.IsNullOrEmpty(baanCatFam))
{
query = query.Where(ph => ph.baan_cat_family_code == baanCatFam);
}
if (!string.IsNullOrEmpty(baanCat))
{
query = query.Where(ph => ph.baan_cat_code == baanCat);
}
if (!string.IsNullOrEmpty(baanSubCat))
{
query = query.Where(ph => ph.baan_sub_cat_code == baanSubCat);
}
//TODO sku filtering here.
List<MappedItem> widgetItems =
from ph in query
let c1 = ph.widgetAssignedCode.CCRCode
group c1 by c1.code_desc into g
select new MappedItem
{
ItemDescription = g.Key.ToUpper(),
ItemCount = g.Count()
}).OrderByDescending(m => m.ItemCount)
.ToList();
Third: the answer to your question.
what causes this error
LinqToSql's query provider cannot translate your local collection into sql. There's only a limitted set of scenarios where it can translate... .Where(ph => idList.Contains(ph.Id)) is translated into an IN clause with 1 parameter per int in idList.
To get around this limitation, you need to convert the local collection into an expression. Start by tranforming each item in the collection into a filtering expression:
List<Expression<Func<WidgetHistory, bool>>> skuFilters =
skuList.Select<string, Expression<Func<WidgetHistory, bool>>>(skuItem =>
ph => ph.ProductMod.StartsWith(skuItem)
).ToList();
Next, a helper method:
public static Expression<Func<T, bool>> OrTheseFiltersTogether<T>(
this IEnumerable<Expression<Func<T, bool>>> filters)
{
Expression<Func<T, bool>> firstFilter = filters.FirstOrDefault();
if (firstFilter == null)
{
Expression<Func<T, bool>> alwaysTrue = x => true;
return alwaysTrue;
}
var body = firstFilter.Body;
var param = firstFilter.Parameters.ToArray();
foreach (var nextFilter in filters.Skip(1))
{
var nextBody = Expression.Invoke(nextFilter, param);
body = Expression.OrElse(body, nextBody);
}
Expression<Func<T, bool>> result = Expression.Lambda<Func<T, bool>>(body, param);
return result;
}
And now putting it all together:
if (skuFilters.Any()) //this part goes into where it says "TODO"
{
Expression<Func<WidgetHistory, bool>> theSkuFilter = skuFilters.OrTheseFiltersTogether()
query = query.Where(theSkuFilter);
}