Entity Framework Foreign Key Queries - entity-framework

I have two tables in my entity framework, objects, and parameters which have a foreign key pointing to the object to which they belong. I want to populate a tree with all the attributes of a certain object. So in order to find those I want to do this:
String parentObject = "ParentObjectName";
var getAttributes = (from o in myDB.ATTRIBUTE
where o.PARENT_OBJECT == parentObject
select o);
However when I try to do this I get an error saying it cannot convert from type OBJECT to string, even though in the database this value is stored as a string. I have a workaround where I get an instance of the parentObject, then go through every attribute and check whether it's parent_object == parentObjectInstance, but this is much less efficient than just doing 1 query. Any help would be greatly appreciate, thanks!

Well, PARENT_OBJECT.ToString() can't be called (implicitly or explicitly) in L2E, but if it just returns a property, you can look at that directly:
String parentObject = "ParentObjectName";
var getAttributes = (from o in myDB.ATTRIBUTE
where o.PARENT_OBJECT.NAME == parentObject
select o);
...note the .NAME

Try this:
String parentObject = "ParentObjectName";
var getAttributes = (from o in myDB.ATTRIBUTE
where o.PARENT_OBJECT.ToString() == parentObject
select o);

Related

How to change the value of a tables attribute using LINQ/LAMBDA?

I have an order table and an orderStatus table, their relationship is as seen below:
I want to be able to change 'StatusID' to the value 2, of a specific order (i am able to get the specific order ID, and have loaded it into an integer variable) using a lambda expression within an action result - would there be any easy way of doing this?
So far i have tried:
//get specific order ID
int currentOrderId = newConfirmedOrderLine.OrderID;
//-----
Order statusChange = new Order();
statusChange.OrderStatus.StatusID = 2;
DBAccessor.SaveChanges();
I am new to linq and lambda, so any explanation with an answer would be greatly appreciated!
If DBAccessor is a DbContext then this could/should work. You need to load the Order entity that you want to change from the DBAccessor.Order DbSet, change it by setting a property, and then call SaveChanges.
var orderStatus = DBAccessor.OrderStatus.First(x => x.StatusID == 2);
var order = DBAccessor.Order.Find(currentOrderId);
order.OrderStatus = orderStatus;
DBAccessor.SaveChanges();

In C#, how do I get a distinct value from an IEnumerable using LINQ?

I have an IEnumerable variable that I want to extract a distinct value from. I know all the entries in the rows of the list have the same value, I just need to get that value.
The method returns an IEnumerable.
The row in the IEnumerable is defined as:
QuoteCovId
AdditionalInterestId
AdditionalInterestsAffiliateId
AdditionalInterestsLastName
AdditionalInterestsBusinessAddrLine1
AdditionalInterestsBusinessCity
AdditionalInterestsBusinessState
AdditionalInterestsBusinessZip
Sampel of code:
IadditionalInterestData = AdditionalInterestData.GetAdditionalInterests(MasterPkgID, Requestor);
// Using linq.
var quotes = from ai in IadditionalInterestData
select Distinct(ai.QuoteCovId);
// Iterate thru to get the 1 value.
foreach (int QuoteCovId in quotes)
{
quoteID = QuoteCovId;
}
var quoteId = AdditionalInterestData.GetAdditionalInterests(MasterPkgID, Requestor)
.FirstOrDefault().Select(f => f.QuoteCovId);
But that method:
AdditionalInterestData.GetAdditionalInterests(MasterPkgID, Requestor);
returns me an IEnumerable which I will use further in my application. Which is what I need.
So how will your suggestion still give me that IEnumerable and give me the quote value which happens to be the same in the collection?
var quoteId = AdditionalInterestData.GetAdditionalInterests(MasterPkgID, Requestor).FirstOrDefault().Select(f => f.QuoteCovId);
Also, I just added your line of code as is and I get an error statement.

LINQ to Entities dynamic DbSet

Is it possible to specify the DbSet of a LINQ to Entities query at run time?
For example if I have a number of different DbSets that have a common property such as "IsExpired" could I pass the DbSet into the query?
So,
Dim query = From o In db.Products Where o.IsExpired = True
Would look something like,
Dim myDynamicName As String
myDynamicName = "Products"
Dim query = From o In db("myDynamicName") Where o.IsExpired = True
The reason why this is not possible becomes more clear when using fluent syntax:
Dim query = db("myDynamicName").Where(Function(o) o.IsExpired)
The function is a
Function Func(Of In T, Out bool)
and the type of T is infered from the IQueryable Of T that precedes it. (This is possible because Where is an extension method, so the IQueryable is its first input parameter). Thus, the compiler knows that o.IsExpired is a valid expression.
That means that db("myDynamicName") must either be specifically typed, which it isn't, or you must supply the type to the Where method. But that's exactly the thing you're trying to circumvent.

EF1: Filtering derived types of entity class using .OfType<> by passing a string value

I have a situation where I'm trying to filter a LINQ select using a derived sub class.
ctx.BaseEntity.OfType<SubClass>() - this works fine.
However I'd like to do this using a string value instead. I've come across a performance barrier when I have lots (>20) Sub Classes and selecting an Entity without using OfType just isn't an option. I have a generic UI that renders from the base class, so I don't know what Class Type will be returned at compile time.
So what I'd like to do is this:
Perform a projected Select where I
return just the SubClassType from
the database
Perform a second select
using this value as the OfType to
only select the relevant related
entity from the database (No mass
unions generated)
int id = 1;
var classType = (from c in ctx.BaseClass.Include("ClassType")
where c.id == id
select new
{
c.ClassType.TypeName
}).First();
BaseClass caseQuery = ctx.BaseClass.OfType<classType.TypeName>()
.Include("ClassType")
.Include("ChildEntity1")
.Include("ChildEntity2")
.Where(x => x.id== id);
But obviously this won't work because OfType requires a Type and not a string.
Any ideas on how I can achieve this?
Update:
As a side note to the original question, it turns out that the moment you project a query that uses a Navigation Property - it builds the monster SQL too, so I've ended up using a stored procedure to populate my ClassType entity from the BaseClass Id.
So I've just got it to work using eSQL, which I'd never used before. I've posted the code here just in case it helps someone. Has anyone else got a more strongly typed solution they can think of?
BaseClass caseQuery = ctx.BaseClass.CreateQuery<BaseClass>("SELECT VALUE c FROM OFTYPE(Entities.[BaseClass],namespace.[" + classType.TypeName + "]) as c")
.Include("ClassType")
.Include("ChildEntity1")
.Include("ChildEntity2")
.Where(x => x.id== id).FirstOrDefault();
To answer the headline question about calling OfType with a string / runtime type, you can do the following:
// Get the type, assuming the derived type is defined in the same assembly
// as the base class and you have the type name as a string
var typeToFilter = typeof(BaseClass)
.Assembly
.GetType("Namespace." + derivedTypeName);
// The use reflection to get the OfType method and call it directly
MethodInfo ofType = typeof(Queryable).GetMethod("OfType");
MethodInfo ofTypeGeneric = method.MakeGenericMethod(new Type[] { typeToFilter });
var result = (IQueryable<Equipment>)generic.Invoke(null, new object[] { equipment });
Combine this with your stored procedure to get the class name and you (should?) avoid the massive join - I don't have table-per-type implementation to play with so I can't test.

How to update a property using Type.GetProperties() method?

I've a collection of a class' properties and would like to update each one's value by iterating over the collection through the index.
1) I create the collection of properties this way
private PropertyInfo[] GetPropertiesOfMyClass()
{
Type myType = (typeof(myClass));
PropertyInfo[] PropertyInfoArray = myType.GetProperties(
BindingFlags.Public |
BindingFlags.Instance);
return PropertyInfoArray;
}
2)Now, I'd like to set up the value of each one depending on the index this way
public void UpdateProperty(MyClass instanceOfMyClass, string valueToUpdate, int index)
{
//TODO:
//1. Get an individual property from the GetPropertyOfMyClass() using index
//2. Update the value of an individual property of the instanceOfMyClass
}
I'd like to be able to call UpdateProperty from a Controller like this:
UpdateProperty(instanceOfMyClass, valueToUpdate, indexOfTheProperty);
Honestly, I do not know how to involve the instanceOfMyClass in the game as GetProperty only plays with myClass.
Since I saw that I can use Name, PropertyType, ... to get information on the property. So, I've tried also GetPropertyOfMyClass()[index].SetValue(...), but I was lost in the arguments of its constructor, so I abandoned.
What I want is to be able to update the value of a property in my collection just by using the index.
Thanks for helping
Your guess was correct. You use SetValue() to update the value - this is how to do it:
GetPropertyOfMyClass()[index].SetValue( instanceOfMyClass, valueToUpdate, null);
The last argument can be null:
Optional index values for indexed properties. This value should be null for non-indexed properties.