Pass parameter to virtual entity data provider plugin - plugins

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");

Related

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.

EF 6, adding entity to DbContext creates duplicate entity

I have a web application (MVC 5, EntityFramework 6). It's connected to an SQL database via a DbContext. I'm having an issue where adding a new entity object creates a duplicate entry in the entity set (but not the DB) and I'm not sure how to stop this from happening.
Controller, whose method is called via an ajax request:
public class CustomerController : Controller
{
MyDBEntities db = new MyDBEntities(); //DbContext
public ActionResult SaveStuff(string customerId, string stuff)
{
Customer customer = db.Single(c => c.ID.Equals(customerId));
Stuff stuff = new Stuff(stuff, customer);
db.Stuffs.Add(stuff);
db.SaveChanges();
return PartialView("MyControl", customer);
}
}
There is a 1-to-many association between Customer and Stuff, and there is a "Stuffs" navigation property in Customer.
Stuff includes fields that are int, string, and DateTime.
The controller method returns a PartialView which is used by JavaScript to refresh the contents of a control.
The "MyControl" control does this:
var stuffs = Model.Stuffs.OrderByDescending(...);
When the control is rendered in this situation, Model.Stuffs contains a duplicate entry. There's an entry with a name of Stuff (probably the new object created in the control method) as well as well as an entry with a name of System.Data.Entity.DynamicProxies.Stuff_<uuid> which is the same exact data (I imagine read from the DB).
This is only a problem when I'm writing into and then reading from an entity set within the same web request. Other/future web requests that cause a read are fine. How can I make this work correctly?
This is happening because the DateTime object is losing precision when it is written into the SQL database (see: SQL Server DateTime vs .NET DateTime). When read back from the DB, it has a different value and therefore does not overwrite the existing "stuff" object that still exists locally in db.Stuffs.
A simple solution is to change the DateTime's setter for Stuff to private and add your own pseudo-setter function that has the rounding built into it:
public void SetTimestamp(DateTime timestamp)
{
//Precision in SQL is lower than in .NET, so just round to tenth seconds
this.Updated = timestamp.AddTicks(- (timestamp.Ticks % (TimeSpan.TicksPerSecond / 10)));
}
Using DateTime2 in the SQL database (Server 2008+) is also an option should you need to maintain that level of precision.

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.

Saving Dropdown list selection with Entity Framework in ASP.NET MVC solution

I'm looking for advice on a decent pattern for dropdown list selection and persistence of the selection with POCO EF please.
I have a list of IEnumerable<Country> in my view model where Country is a POCO loaded via EF. There is an Address property on the view model that takes the current or user selected value on it's Country property. Within the view I display these via a Html.DropdownListFor() thus:
Html.DropDownListFor(model => model.Address.Country.Id, new SelectList(Model.Countries,"Id","Name",model.Address.Country.Id)
So far so good and it all works on postback with the default ModelBinder providing me with a view model with the Address.Country populated. However Address.Country is of course only populated with the Id field with default model binding.
Trying to send the Address update back to the DB through EF blows up as this is seen as a new object which doesn't have it's full object graph loaded, only the Id set.
Now I can fix this by loading the full Country object from the db into the Address.Country property on postback before saving based on the selected Id. But this seems like a lot of hard work for anything beyond a simple object graph.
The most "elegant" solution I could think of would be a custom model binder for Country but then that would require the Model Binder to know about the repository for retrieving the full EF object which doesn't seem right to me. I'd also have to repeat this for all other Entities used in Dropdown lists.
Hope this makes sense and any feedback on how others are doing this would be appreciated.
If you set Address.Country to an object, EF expects it to be a full object that's part of the current context, but EF does recognize foreign keys: If your Address object has both a CountryID property and a Country property, it should accept Address.CountryID being set as long as Address.Country itself is null.
In your Address class declare country as virtual
public class Address
{
public virtual Country Country;
}
try this and let me know if it works, Virtual supports lazyloading and you don't have to query explicitly

How to prepare data for display on a silverlight chart using WCF RIA Services + Entity Framework

I've used WCF RIA services with Entity Framework to build a simple application which can display and updates data about school courses. This was done by following the Microsoft tutorials. Now I would like to have a chart which shows a count for how many courses are on a key stage.
Example:
Key Stage 3 - 20 courses
Key Stage 4 - 32 courses
Key Stage 5 - 12 courses
Displayed on any form of chart. I have no problem binding data to the chart in XAML. My problem is that I do not know how to correct way of getting the data into that format. The generated CRUD methods are basic.
I have a few thoughts about possible ways, but don't know which is correct, they are:
Create a View in SQL server and map this to a separate Entity in the Entity Data Model. Generating new CRUD methods for this automatically.
Customise the read method in the existing DomainService using .Select() .Distinct() etc. Don't know this syntax very well labda expressions/LINQ??? what is it? Any good quickstarts on it?
Create a new class to store only the data required and create a read method for it. Tried this but didn't know how to make it work without a matching entity in the entity model.
Something I am not aware of.
I'm very new to this and struggling with the concepts so if there are useful blogs or documentation I've missed feel free to point me towards them. But I'm unsure of the terminology to use in my searches at the moment.
One way to is to build a model class. A model is a class that represents the data you wish to display. For example i might have a table with 10 fields but i only need to display 2. Create a model with these two properties and return that from your data layer.
you can use entity framework to pump data into a new class like so
Model Class:
public class Kitteh
{
public string Name { get; set; }
public int Age { get; set; }
}
Entity Query:
public Iqueryable<Kitteh> getKittehz
{
var result = from x in Data.TblCats
select new Kitteh
{
Name = x.Name,
Age = x.Age
}
return result;
}
If you are interested in the best practices approach to building silverlight applications I would suggest you research the MVVM pattern.
http://www.silverlight.net/learn/videos/silverlight-4-videos/mvvm-introduction/
http://www.silverlight.net/learn/tutorials/silverlight-4/using-the-mvvm-pattern-in-silverlight-applications/
I am attempting a similar piece of work.
I will tell you the approach I am going to use and maybe that can help you.
I am going to create a class in the silverlight project to describe the chartItem: It will have 2 string properties : Key and Value.
Then create a collection object...In your case, this could be a class that has one property of type Dictionary<string,string> myCollection... or ObservableCollection<ChartItem> myCollection
The next step is to do a ForEach loop on the data coming back from the server and Add to your Collection.
myCollection.Add(new chartItem{ Key= "Key Stage 3", Value = "20 Courses" });
myCollection.Add(new chartItem{ Key= "Key Stage 4", Value = "60 Courses" });
myCollection.Add(new chartItem{ Key= "Key Stage 5", Value = "10 Courses" });
... more to follow if you are still looking for an answer
There is no easy way to include Views in Entity Framework as it does not allow any table/view to be included without "Key" (PrimaryKey) which will cause more efforts as you will have to map view manually in EDMX and then map keys etc.
Now we have found out an alternative approach,
Create View called ChartItems in your DB
Create LinqToSQL file ViewDB
Drag View ChartItems in ViewDB
Create ChartItem[] GetChartItems method in your RIA Domain Service Class as follow
public ChartItem[] GetChartItems(..parameters...){
ViewDB db = new ViewDB();
return db.ChartItems.Where(...query mapping...).ToArray();
}
RIA Domain Service Class can contain any arbitrary method that you can directly invoke from client with parameters. It is as simple as calling a web service. And you have to return an array because IQueryable may or may not work in some cases, but we prefer Array. You can try IQueryable but it may not work correctly against linq to SQL.