Class that is member of another class is always null [duplicate] - c#

This question already has answers here:
Load child entity on the fetch of the Parent entity EFCore
(3 answers)
Why EF navigation property return null?
(7 answers)
Closed 2 years ago.
I am working on a C# WPF project using Entity Framework code first.
I have a class that has an instance of another class as its member. I am trying to access the value of a property of the member class. I can get the value this way:
var com = context.MyParentClass.Where(p => (p.Identity == id)).Select(c =>
new
{
id = c.Identity,
PropertyValue = c.MyChildClass.PropertyValue
}
);
foreach(var item in com)
{
string xx = item.PropertyValue;
MessageBox.Show(xx);
}
But when I try to get the value without the select, the member class is always null:
var com = db.MyParentClass.SingleOrDefault(b => b.Identity == id);
string xx = com.MyChildClass.PropertyValue; //MyChildClass is null
MessageBox.Show(xx);
Does anyone know what is going on here? How do I get around the null-problem?

You have to make sure that lazy loading is enabled or not.
context.Configuration.ProxyCreationEnabled should be true.
context.Configuration.LazyLoadingEnabled should be true.
Navigation property should be defined as public, virtual. The
context will NOT do lazy loading if the property is not defined as
virtual.
You can use Include for eager loading also. Thank you #CodeCaster for the suggestion.
Reference: https://www.entityframeworktutorial.net/lazyloading-in-entity-framework.aspx

Related

Recognize whether LazyLoading is active in Entity Framework directly on an entity

In a simple web API call to receive some data, I set db.Configuration.LazyLoadingEnabled = false;. Then I retrieve elements from the database via Entity Framework. These are converted into an exchange object using an explicit cast. This exchange class in turn contains conversions using an explicit cast again. Now I would like to know within such a cast method whether lazy loading is active or not, without knowledge of the actual database context. Is there a way to determine this using only the proxy object?
The reason is that I would like to set a list of child elements in my exchange object to NULL if it was not loaded in the proxy object. However (according to my observation) the lists are simply created empty with zero child elements. As a result, I cannot see exactly whether there are actually no assigned children in the database, or whether the data has not been loaded at all. Is there a reliable way to find this out?
public async Task<IEnumerable<Models.DataExchange.Plant>> GetPlantsWithStorages() {
db.Configuration.LazyLoadingEnabled = false;
// Get list from database
List<Models.Plant> plantList = await db.Plants
.IncludeOptimized(plant => plant.PlantAreas)
.IncludeOptimized(plant => plant.PlantAreas.Select(plantArea => plantArea.Storages))
.IncludeOptimized(plant => plant.PlantAreas.Select(plantArea => plantArea.LoadingBays))
.OrderBy(plant => plant.Name)
.ToListAsync();
// Cast and return result to client
return plantList.Select(p => (Models.DataExchange.Plant)p);
}
public static explicit operator StorageLocation(Storage storage) {
if (storage == null)
throw new ArgumentNullException(nameof(storage));
// storage.ChargeCarrier_Storage won't be filled in my example.
// However, the list is not null, but an empty list.
// Is there something like storage.ChargeCarrier_Storage.IsLoaded?
return new StorageLocation() {
Description1 = storage.Description1,
Description2 = storage.Description2,
ID_Storage = storage.ID,
ID_StorageType = storage.ID_StorageType,
ChargeCarriers = storage.ChargeCarrier_Storage?.Select(ccs => (ChargeCarrier)ccs.ChargeCarrier)
};
}
without knowledge of the actual database context. Is there a way to determine this using only the proxy object?
You can examine the runtime type of the entity. It will be a proxy type, from a dynamic assembly, isntead of an Entity type from the Assembly that defines your Entities. Eg
bool IsProxy(object entity)
{
return System.Reflection.Assembly.GetExecutingAssembly() != entity.GetType().Assembly;
}
I cannot see exactly whether there are actually no assigned children in the database, or whether the data has not been loaded at all. Is there a reliable way to find this out?
The right way to do that is through the DbContext. eg
var areasLoaded = db.Entry(plant).Reference(a => a.PlantAreas).IsLoaded();

Use Like in Linq query EF Core [duplicate]

This question already has answers here:
Like Operator in Entity Framework?
(9 answers)
Closed 3 years ago.
I have the below method in the EF Core application
public List<Prj_Detail> GetByOrg(string org)
{
var data = _context.Prj_Details.Where(w => w.Account_Name == org).ToList();
return data;
}
Here instead of == I need to check for Like how can I do that in my method
Like others have said you can do a Contains operator however in some cases this casues an unncessary TSQL casting. Instead you could use the in-built Entity Framework functions like so:
_context.Prj_Details.Where(EF.Functions.Like(w.Account_Name, org)).ToList();
Have you tried using Contains?
var data = _context.Prj_Details.Where(w => w.Account_Name.Contains(org)).ToList();
You can use StartsWith and EndsWith too.
Here's more information about it.
Could try with Contains to filter.
Please refer the below code.
depending on LeftRim/RightTrim/upperCase/LowerCase
public List<Prj_Detail> GetByOrg(string org)
{
var data = _context.Prj_Details.Where(w => w.Account_Name.Contains(org)).ToList();
return data;
}

Create reference to a class from a string variable [duplicate]

This question already has answers here:
C# Reflection: How to get class reference from string?
(6 answers)
Closed 7 years ago.
Here is what I need to do;
string className = "Customer";
List<className> myList = new List<className>();
className can be any of my Entity Framework classes. I have used Customer just as an example.
I hope this is possible. If so, how?
UPDATE:
I also need to use this approach for retrieving data from an Entity Framework dbContext. For example...
string className = "Customer";
var myData = db.Set<className>();
Sorry. Not sure if I should have created another question here or updated this one. Be gentle with me. I'm new here. :o)
If you want you can use reflection in this case, but I would think over another solution.
Type type = Type.GetType("Namespace.ClassName");
Type listType = typeof(List<>).MakeGenericType(new [] { type } );
IList list = (IList)Activator.CreateInstance(listType);
You can use:
Type customerType = Type.GetType("this.is.a.namespace.Customer");
Related: other question

Dynamic table name in linq [duplicate]

This question already has answers here:
Querying data using Entity Framework from dynamically created table
(2 answers)
Dynamically set the table name in LINQ query
(3 answers)
Closed 8 years ago.
I'm trying to execute some LINQ commands using a dynamic table name. For example, instead of:
var o = (from x in context.users select x);
I want to use something like:
var o = (from x in getTableObjectByName("users", context) select x);
More or less. Here's the code I have so far, which both compiles and runs:
using (MySiteEntities ipe2 = new MySiteEntities()) {
var propinfo1 = Type.GetType("MySiteNamespace.MySiteEntities").GetProperty("users");
var propval1 = propinfo1.GetValue(ipe2, null);
}
That runs, but always returns zero records. The users table most definitely contains records, and in any case when I call it directly using the first method above I get all of the records as expected. How can I modify my code to actually pull down records, rather than just an empty collection?
Edit: I've also tried this:
using (MySiteEntities ipe = new MySiteEntities())
{
var prop = Type.GetType("MySiteNamespace.MySiteEntities").GetProperty("users");
Type dbsetType = typeof(DbSet<>);
dbsetType = dbsetType.MakeGenericType(Type.GetType("MySiteNamespace.user"));
Type t = dbsetType.GetType();
var val = prop.GetValue(ipe, null);
}
In this case, the code not only runs, but actually returns the results as expected. However, val is an Object. I need to cast it to the type DbSet<user>, which would be easy enough, except that the parameter user is only known at runtime....the cast needs to be dynamic as well. I've tried using Convert.ChangeType(val, t);, but that throws an
InvalidCastException (Object must implement IConvertible).
How can I convert the val variable to an actually usable object?
No idea if this is relevant, but this is on EntityFramework 4.
In your DbContext class, add a method say called Set that returns:
public DbSet Set(string name)
{
// you may need to fill in the namespace of your context
return base.Set(Type.GetType(name));
}
Which you can query like this:
using (var db = new YourDataContext())
{
// Since your DbSet isn't generic, you can can't use this:
// db.Set("Namespace.EntityName").AsQueryable().Where(a=> a.HasSomeValue...
// Your queries should also be string based.
// Use the System.Linq.Dynamic nuget package/namespace
var results = db.Set("Namespace.EntityName")
.AsQueryable()
.Where("SomeProperty > #1 and SomeThing < #2", aValue, anotherValue);
// you can now iterate over the results collection of objects
}
More information on System.Linq.Dynamic can be found here

AutoMapper - Why it is overwriting whole object? [duplicate]

This question already has answers here:
Automapper: Update property values without creating a new object
(4 answers)
Closed 4 years ago.
I don't understand why it's overwriting my whole object. The reason is that I get my User object from db an I want to assign new values from DTO. Instead of just adding those new values it's creating new object that has new values but all previous are set to null.
How can I make sure that in this case he will "upgrade" my object, not create new one?
Scenario
/users/{id} - PUT
// User has id, username, fullname
// UserPut has fullname
public HttpResponseMessage Put(int id, UserPut userPut)
{
var user = _db.Users.SingleOrDefault(x => x.Id == id); // filled with properties
Mapper.CreateMap<UserPut, User>();
user = Mapper.Map<User>(userPut); // now it has only "fullname", everything else set to null
// I can't save it to db because everything is set to null except "fullname"
return Request.CreateResponse(HttpStatusCode.OK, user);
}
The Mapper.Map has an overload which takes a source and a destination object. In this case Automapper will use the given destination object and does not create a new object.
So you need to rewrite your Mapper.Map to:
Mapper.Map<UserPut, User>(userPut, user);

Categories