How to get data from relationship objects in entity framework? - entity-framework

I have 2 Entity objects that i mapped in Entityframework
I have relationship between users and Messages
I want to get all messages of specific user so i load the data from users table to specific user object:
var user = (from u in context.Users
where u.u_username == username
select u).First();
Now, how can i get all messages of this user , i notice that i can do:
var messages = user.Messages;
But i got nothing.
Is it correct?
How can i used this syntax and to get all message of the specific user?
I used .net4
Is it possible to do

If you want to lazy load the Messages of the user you can make the Messages property virtual.
public class User
{
//other properties
public virtual ICollection<Message> Messages;
}
Or you can eager load Messages using Include function
var user = (from u in context.Users.Include("Messages")
where u.u_username == username
select u).First();
Finally it maybe the case that you have not configured the Messages property with EF.

Related

Pass parameter to virtual entity data provider plugin

I'm aiming to show virtual entity records on a subgrid on the form of a custom entity (say, Client). I have created a virtual entity, custom data provider and registered the required plugin. So far things work fine; I load the form, subgrid loads with the data from external webservice.
Now, I want to pass a string field on the form (say, Client.ExternalId) as a parameter to the retrieveMultiple plugin so that I can use this field to query the datasource.
The retriveMultiple plugin steps (registered automatically when custom data provider was set up) show that it was registered on the virtual entity and not Client entity. Since it gets executed on load of the subgrid on the Client entity form I am not sure how I can pass a field to the plugin.
Can someone please give some guidance on how to achieve this?
Version 1710 (9.2.22103.194) online
Thanks
If the virtual entity has an N:1 relationship with the main entity and the subgrid is configured to show related records, then you can do like this:
// first, get the whole query
var query = context.InputParameterOrDefault<QueryExpression>("Query");
// next, get the linkEntity and then the linkFilter
var linkFilter = query.LinkEntities.FirstOrDefault(x => x.LinkToEntityName == "mainEntityLogicalName").LinkCriteria;
// next, get the main entity id
var mainEntityId = linkFilter.Conditions.FirstOrDefault(x => x.AttributeName == "mainEntityIdFieldName").Values.FirstOrDefault() as Guid?;
// finally, retreive main entity to get the Client.ExternalId
var mainEntity = orgSvc.Retrieve("mainEntityLogicalName", mainEntityId.Value, new ColumnSet("Client.ExternalId"));
var clientExternalId = mainEntity.GetAttributeValue<string>("Client.ExternalId");

How can the Entity type of a PartyId be determined?

Using Dynamics CRM 2011. I am learning about ActivityPartys.
Since the PartyId of an ActivityParty is an EntityReference, in order to set the PartyId, you need to know the Entity type.
I am trying to create a new PhoneCall (in a plugin) using the same Recipient as an existing phone call. I can retrieve the recipient's PartyId Guid using LINQ from the ActivityPartySet, but how can I determine the Entity Type, which could be either Account or Contact?
Conversely, is it possible to set the PartyId without knowing the EntityLogicalName?
Update:
Thanks for responding but I either misunderstood you or you misunderstood what I am trying to ascertain. Here's my code right now:
// Get the oldPhoneCall's To ActivityParty list:
EntityCollection Recipients = oldPhonecall.GetAttributeValue<EntityCollection>("to");
// Use the first one to find the partyId
// Need to do it this way because we don't know if partyId points to an Account or a Contact:
Guid activityPartyId = Recipients.Entities[0].Id;
var activityParty2 = new Xrm.ActivityParty();
context.GetWorkflowHelper().serviceContext.ClearChanges();
var queryParty = from ap in context.GetWorkflowHelper().serviceContext.ActivityPartySet
where ap.ActivityPartyId.Equals(activityPartyId)
select new { ap.PartyId, ap.LogicalName };
foreach (var party in queryParty)
{
activityParty2.PartyId = new EntityReference(party.LogicalName, party.PartyId.Id);
}
I found that in the foreach, party.LogicalName is ActivityParty. This is not the entity type of oldphonecall's recipient, which in my test case is Contact but in other cases is Account.
How do I determine that entity logical name? Where have I gone wrong?
Update2:
In SQL I can see field PartyObjectTypeCode and I know I can map that to an entity type (where 1 = Account, 2= Contact, etc.) but when I query the ActivityPartySet, no such field seems to exist.
Update 3:
Got it -
foreach (var party in queryParty)
{
activityParty2.PartyId = new EntityReference(party.PartyId.LogicalName, party.PartyId.Id);
}
how can I determine the Entity Type, which could be either Account or
Contact?
PartyId is of the type EntityReference where LogicalName would give you the related entity type.
var entityLogicalName = context.EmailSet.FirstOrDefault().To.FirstOrDefault().PartyId.LogicalName
Conversely, is it possible to set the PartyId without knowing the
EntityLogicalName?
No, when setting a CRM entity reference both Id and LogicalName are required fields.
In order to set the PartyId you need to know the LogicalName of the entity.
You didn't post the code, but if you are able to retrieve the Id from a recipient you can retrieve also the LogicalName (they are stored as EntityReference)

EF and OData entity relationships - need some basic help bad

I have what I think is a very basic problem. Created an OData web server to serve up Customers and Orders. Each order has a relationship to a Customer. Code snippet is:
public class Customer
{
int Id {get;set;}
...
}
public class Order
{
int Id {get;set;}
public virtual Customer customer {get;set;}
...
}
When the web service creates the db and tables, it all looks good. If I add a Order object (in the orders controller) with the customer object set correctly, the generated Customer_Id foreign key field gets filled in. My problems are:
On the client, when I add an order to the OData container, it does not serialize the customer object so the controller gets a null value. When I set the customer object in the controller, EF seems to handle the process fine putting in the right Id for that customer.
Am wondering if I need a .AddLink call on the client app. If so, not sure what to add as all my attempts throw exceptions.
container.AddLink(order.Customer,"Customer",order); (throws exception that order does not have a settable property)
When I try and retrieve an order object, the customer object is always null. I have disabled LazyLoading and even have a .Include(o=>o.Customer) in the orders controller get handler.
Think I am missing something pretty basic, just not getting what I need to do to make this work. I do have an embedded complex type that is working as expected, just can't get the entity relationships to flow in the client.
Thanks for any help you can provide.

Attaching an related entity to new entity, without retrieving from database

I've just started working with Web API this week, and I'm struggling with something which I think should be quite simple, but haven't been able to find the answer for yet. Perhaps I'm searching using the wrong terms.
One of the calls to the API passes through a GUID. I need to create a new entity (using Entity Framework) and set one of the relations to this newly passed in GUID. This GUID is the ID of a different entity in the database.
I'm struggling to attach the entity via the relation without fetching the whole entity too.
For example,
public void DoWork(IList<Guid> userGuids)
{
Order order = new Order() // This is an entity
{
CreateDate = DateTime.Now,
CreatedBy = "Me",
Items = (from i in this.Model.Items
where i.Id == userGuid
select i).ToList<Item>();
}
Model.Orders.Add(order);
Model.SaveAll();
}
In the above, I have to do a database call to attach the Item entities to the Order. Is there not a way around this? Seems very redundant to retrieve the whole entity objects when I only require their IDs (which I already have anyway!)!
One solution is stub entities as asked here: Create new EF object with foreign key reference without loading whole rereference object
Link to the source blog referenced: http://blogs.msdn.com/b/alexj/archive/2009/06/19/tip-26-how-to-avoid-database-queries-using-stub-entities.aspx
Snip from the blog - to be applied to your situation:
Category category = new Category { ID = 5};
ctx.AttachTo(“Categories”,category);
Product product = new Product {
Name = “Bovril”,
Category = category
};
ctx.AddToProducts(product);
ctx.SaveChanges();
This way (in the example) the Product is saved without ever loading the Category object.

Delete a child from an aggregate root

I have a common Repository with Add, Update, Delete.
We'll name it CustomerRepository.
I have a entity (POCO) named Customer, which is an aggregate root, with Addresses.
public class Customer
{
public Address Addresses { get; set; }
}
I am in a detached entity framework 5 scenario.
Now, let's say that after getting the customer, I choose to delete a client address.
I submit the Customer aggregate root to the repository, by the Update method.
How can I save the modifications made on the addresses ?
If the address id is 0, I can suppose that the address is new.
For the rest of the address, I can chose to attach all the addresses, and mark it as updated no matter what.
For deleted addresses I can see no workaround...
We could say this solution is incomplete and inefficient.
So how the updates of aggregate root childs should be done ?
Do I have to complete the CustomerRepository with methods like AddAddress, UpdateAddress, DeleteAddress ?
It seems like it would kind of break the pattern though...
Do I put a Persistence state on each POCO:
public enum PersistanceState
{
Unchanged,
New,
Updated,
Deleted
}
And then have only one method in my CustomerRepository, Save ?
In this case it seems that I am reinventing the Entity "Non-POCO" objects, and adding data access related attribute to a business object...
First, you should keep your repository with Add, Update, and Delete methods, although I personally prefer Add, indexer set, and Remove so that the repository looks like an in memory collection to the application code.
Secondly, the repository should be responsible for tracking persistence states. I don't even clutter up my domain objects with
object ID { get; }
like some people do. Instead, my repositories look like this:
public class ConcreteRepository : List<AggregateRootDataModel>, IAggregateRootRepository
The AggregateRootDataModel class is what I use to track the IDs of my in-memory objects as well as track any persistence information. In your case, I would put a property of
List<AddressDataModel> Addresses { get; }
on my CustomerDataModel class which would also hold the Customer domain object as well as the database ID for the customer. Then, when a customer is updated, I would have code like:
public class ConcreteRepository : List<AggregateRootDataModel>, IAggregateRootRepository
{
public Customer this[int index]
{
set
{
//Lookup the data model
AggregateRootDataModel model = (from AggregateRootDataModel dm in this
where dm.Customer == value
select dm).SingleOrDefault();
//Inside the setter for this property, run your comparison
//and mark addresses as needing to be added, updated, or deleted.
model.Customer = value;
SaveModel(model); //Run your EF code to save the model back to the database.
}
}
}
The main caveat with this approach is that your Domain Model must be a reference type and you shouldn't be overriding GetHashCode(). The main reason for this is that when you perform the lookup for the matching data model, the hash code can't be dependent upon the values of any changeable properties because it needs to remain the same even if the application code has modified the values of properties on the instance of the domain model. Using this approach, the application code becomes:
IAggregateRootRepository rep = new ConcreteRepository([arguments that load the repository from the db]);
Customer customer = rep[0]; //or however you choose to select your Customer.
customer.Addresses = newAddresses; //change the addresses
rep[0] = customer;
The easy way is using Self Tracking entities What is the purpose of self tracking entities? (I don't like it, because tracking is different responsability).
The hard way, you take the original collection and you compare :-/
Update relationships when saving changes of EF4 POCO objects
Other way may be, event tracking ?