Make select method after FindAsync() method? - entity-framework

I use entity framework 6.
I use FindAsync() extension to retrieve record from database:
protected readonly DbSet<T> Table
return await Table.FindAsync(id);
How can I make select on this Table.FindAsync(id) row to retrieve specific records from retrieved row?

Related

Updating entity without having the know primary key

Given the following code, how can I add an element to one of the properties of an entity without knowing its Id and retrieving it from the database?
public async Task BookInPersonVisitAsync(Guid propertyId, DateTime dateTime, CancellationToken token)
{
var entity = new OnBoardingProcessEntity{ ExternalId = propertyId };
DbContext.OnBoardingProcesses.Attach(entity);
entity.OnBoardingProcessVisits.Add(new OnBoardingProcessVisitEntity
{
DateTime = dateTime,
Occurred = false
});
await DbContext.SaveChangesAsync(token);
}
ExternalId is just a guid we use for external reference. This doesnt work cause it does not have the id set, but without hitting the database we cant have it.
With entity framework if you have to reference an entity (referencedEntity) from another entity (entity) you have to know referencedEntity.
Otherwise you can add just add the entity setting the referencedEntity to null.
To know the referencedEntity or you know the Id or you have to retrieve it in some ways (from the database).
In SQL (DML) if (and only if) ExternalId is a candidate key noy nullable you can insert the OnBoardingProcessVisit record with a single roundtrip but the insert statement will contain an inner query.
OnBoardingProcessVisit.OnBoardingProcess_Id = (
SELECT
Id
FROM
OnBoardingProcess
WHERE
ExternalId = #propertyId)
EDIT
No way to generate that query with EF. You can have a look to external components (free and not free, for example EntityFramework Extended but in this case I think that doesn't help).
In this case I probably would try to use standard entity framework features (so 1 roundtrip to retrieve the OnBoardingProcess from the ExternalId).
Then, if the roundtrip is too slow, run the SQL query directly on the database.
About performances (and database consistency) add a unique index on OnBoardingProcess.ExternalId (in every case).
Another suggestion if you decide for the roundtrip.
In your code, the entity will be a proxy. If you don't disable lazy load, using your code you will do one more roundtrip when you will access to property
entity.OnBoardingProcessVisits (in the statement entity.OnBoardingProcessVisits.Add).
So, in this case, disable lazy load or do the same using a different way.
The different way in your case is something like
var onBoardingProcessVisitEntity new OnBoardingProcessVisitEntity
{
DateTime = dateTime,
Occurred = false,
OnBoardingProcess = entity
});
DbContext.OnBoardingProcessVisits.Add(onBoardingProcessVisitEntity);
await DbContext.SaveChangesAsync(token);

How to use joinwith in yii2 framework

I have created a curd called 'Status' and it is working properly. I have created a new Model(with table) called relation(id, status_id, user_id).
Now I want to join relation table to Status while showing records with some custom condition.
How to do that?
To make connection between two tables with foreign key create function in model Relation like this.
public function getStatus()
{
return $this->hasOne(Status::className(),['id'=>'status_id']);
}
To access value of status from relation model object, you can like this.
$relation->status->name_of_attribute;
$relation one object from Relation model.

Can I lazy load a navigation property by delegating to a stored procedure in EF?

I have the following customer class:
public class Customer
{
public long Id { get; set; }
public virtual ICollection<Order> Orders { get; set; }
}
My database has Customers and Orders tables, but no foreign key relationships. Orders for a customer are obtained using a stored procedure that takes the customer ID and returns the order rows. I can't modify the database.
I know how to call the stored procedure from Entity Framework, but, is it possible to configure the DbContext using the fluent API so that accessing the Orders collection of a customer object would lazy load the entities via a call to the stored procedure?
I'm using the latest version of EF.
No, you can't. Lazy loading is coded in the proxy object that EF creates (if possible), there's no way to intercept/configure the way proxies are generated.
It's not even possible to map the default read action of a DbSet to a stored procedure. It's always a query. Only create, update and delete can be mapped to stored procedures.
The reason (I think) is that stored procedures are not composable, so if in a complex LINQ query one entity would be mapped to a stored procedure (for reading) it wouldn't be possible to turn the query into one SQL statement.

Entity framework and pure POCO update

How do I do an update on a pure POCO object using entity framework 4?
Lets say I change the person's first name and call the repository in this manner:
public User Update(User user)
{
//User originalUser = GetUser(user.UserId);
//Is there a way to update the values that are only changed?
context.Users.Attach(user);
context.ObjectStateManager.ChangeObjectState(user, EntityState.Modified);
return user;
}
I dont want null values to update the database to null. For eg. Suppose I have LastName as a property but when passing the object to the update function, it was null. Am I going to have to get the originalUser and then update each property accordingly?
"update each property accordingly?"
No, you can use,
context.ObjectStateManager.TryGetObjectStateEntry(newItem, out entity);
// this will gives you the entity present in db and after that I suggest to write your code to change the state and save.
Also suggest you to read this
for more info on tracking changes in POCO entities

ObjectSet and ResultSet on stored procedure on EF and Domain Service

In EF 4, the default ObjectSet is available for each entity. For example, I have table Employee, after gererated Entity Model, EF will create ObjectSet on Employee.
Then when using wcf ria service, the default query will be like:
public IQueryable GetEmployee()
{
return this.ObjectContext.Employees;
}
With objectSet, I can apply include on the result like:
return this.ObjectContext.Employees.Include("Department");
Then I create a stored procedure say MySearchForEmployee and import it as function. the result is mapped to entity Employee. When call the function, the result will be ResultSet, not ObjectSet.
I want to similar method available for domain service by call the stored procedure like:
public IQueryable<Employeer> GetMySearch(string keyword)
{
return this.ObjectContext.MySearchForEmployee(keyword).Include("Department");
}
But I can't becuase above code event can't pass syntax checking.
I tried following way to convet the result type:
var results = this.ObjectContext.MySearchForEmployee(keyword);
var objsets = (ObjectSet<Employee>) results;
then I got error as:
Cannot convert type 'System.Data.Objects.ObjectResult' to 'System.Data.Objects.ObjectSet'
How to implement this request?
There is no reason to use an ObjectSet, because you cannot include multiple entity sets in one query from a stored procedure. This is not supported in the Entity Framework.
You could try the EFExtensions project, it has extensions to load multiple entity sets from one query.