Question

I had really hard time writing the title, I am not sure if it's good enough.

I am making a routing application. I am using Entity Framework. Because my map is an undirected graph, I need to retrieve the edges twice (A->B, B->A) from the database, where they are stored only as (A->B).

So far, I had this:

public IList<Edge> GetBatteryCenterEdges(string name)
{
    var query =
        from edges in context.Edge
        where (edges.BatteryStation.name.Equals(name) || edges.BatteryStation1.name.Equals(name))
        select edges;

    return query.ToList();
}

But that would return only A->B.

I must notice I am fairly new into C# and LINQ.

I tried doing:

IEnumerable<Edge> test = query.Select(x => new Edge { BatteryStation = x.BatteryStation1, BatteryStation1 = x.BatteryStation });

(BatteryStation and BatteryStation1 are basically the vertices)

Then I tried to do

query.Union(test)

But that wouldn't return any of the reversed Edges.

So I tried returning the test and it would result in:

The entity or complex type 'CarBatteryModel.Edge' cannot be constructed in a LINQ to Entities query.

How can I reverse those Edge objects from the database in the best way possible?

My classes:

Edge comes from ET:

public partial class Edge
{
    public virtual BatteryStation BatteryStation { get; set; }
    public virtual BatteryStation BatteryStation1 { get; set; }
}

BatteryCenter inherits from the BatteryStation which comes from ET:

public class BatteryCenter : BatteryStation
{
    public IList<Edge> Edgelist;

    public BatteryCenter()
    {
        Edgelist = new List<Edge>();
    }
}
Was it helpful?

Solution

I would use method syntax for this:

var query = context.Edge.Where(edge=>edge.BatteryStation.name.Equals(name) ||
                                     edge.BatteryStation1.name.Equals(name))
                   .AsEnumerable()
                   .SelectMany(edge => new []{ edge,
                                            new Edge{
                                             BatteryStation = edge.BatteryStation1,
                                             BatteryStation1 = edge.BatteryStation
                                            }
                               });
return query.ToList();

Update:

Try bulding Expression tree:

var query = context.Edge.Where(edge=>edge.BatteryStation.name.Equals(name) ||
                                     edge.BatteryStation1.name.Equals(name));
var edgeParam = Expression.Param(typeof(Edge),"edge");
var edgeBA = Expression.New(typeof(Edge));
var bind1 = Expression.Bind(typeof(Edge).GetProperty("BatteryStation"),
                            Expression.Property(edgeParam, "BatteryStation1"));
var bind2 = Expression.Bind(typeof(Edge).GetProperty("BatteryStation1"),
                            Expression.Property(edgeParam, "BatteryStation"));
var edgeBAInit = Expression.MemberInit(edgeBA, bind1, bind2);
var edgeArray = Expression.NewArrayInit(typeof(Edge),edgeParam, edgeBAInit);
var selectManyLambda = Expression.Lambda<Func<Edge,IEnumerable<Edge>>>(
                                  edgeArray, edgeParam);
return query.SelectMany(selectManyLambda).ToList();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top