Invoke operation in wcf ria services not able to include foriegn key tables - mvvm

Hi.
I m using a Invoke Operation which return a class "Product"
public Product GetProductById(int Id)
{
Product Record = this.ObjectContext.Product.Include("Order_Detail").Where(d=>d.ProductID=Id).FirstOrDefault()
return Record;
}
But i m not able to get Order_Detail in the the completed event of the class
InvokeOperation<Product> Invk = ObjProduct.GetProductById();
Invk.Completed += (sender, e) =>
{
if (!Invk.HasError)
{
Product ObjProduct = Invk.Value;
Order objorder=ObjProduct.Order_Detail;
}
};
i m getting ObjProduct.Order_Detail as Null i not known why i m not able to include Order_Detail in this Product entity
I have written [Include] in metadata as well
[Include]
public Order Order { get; set; }
But Still i m not able to get Order_Detail In the collection.
Waiting for a positive response.

This is the expected behavior. Invokes are meant to execute an operation on the server or retrieve a simple object. As you can see, the InvokeOperation callback don't contains the usual Entities/AllEntities properties that make room for Included Entities. I suggest you to use a standard load operation with a parameter to get your data.
public IQueryable<Product> GetProductById(int Id)
{
return this.ObjectContext.Product.Include("Order_Detail").Where(d=>d.ProductID=Id);
}
If what you're trying to achieve is "Non Accumulating Execution" (i.e. don't load your domainContext's entityContainer with the result of the query) than have a look at this post from Mathew Charles

Related

f#: Only parameterless constructors and initializers are supported in LINQ to Entities

I am trying to get Envelope's back from a query. Envelope is defined as follows.
[<CLIMutable>]
type Envelope<'T> = {
Id : Guid
StreamId: Guid
Created : DateTimeOffset
Item : 'T }
MyLibAAS.DataStore.MyLibAASDbContext is a EF DbContext written in c#. When I extend it in f# as follows, I get the error: Only parameterless constructors and initializers are supported in LINQ to Entities.
type MyLibAAS.DataStore.MyLibAASDbContext with
member this.GetEvents streamId =
query {
for event in this.Events do
where (event.StreamId = streamId)
select {
Id = event.Id;
StreamId = streamId;
Created = event.Timestamp;
Item = (JsonConvert.DeserializeObject<QuestionnaireEvent> event.Payload)
}
}
If I return the event and map it to Envelope after the fact, it works fine.
type MyLibAAS.DataStore.MyLibAASDbContext with
member this.GetEvents streamId =
query {
for event in this.Events do
where (event.StreamId = streamId)
select event
} |> Seq.map (fun event ->
{
Id = event.Id
StreamId = streamId
Created = event.Timestamp
Item = (JsonConvert.DeserializeObject<QuestionnaireEvent> event.Payload)
}
)
Why does this make a difference? The Envelope type is not even a EF type.
How F# records work
F# records get compiled into .NET classes with read-only properties and a constructor that takes values of all fields as parameters (plus a few interfaces).
For example, your record would be expressed in C# roughly as follows:
public class Envelope<T> : IComparable<Envelope<T>>, IEquatable<Envelope<T>>, ...
{
public Guid Id { get; private set; }
public Guid StreamId { get; private set; }
public DateTimeOffset Created { get; private set; }
public T Item { get; private set; }
public Envelope( Guid id, Guid streamId, DateTimeOffset created, T item ) {
this.Id = id;
this.StreamId = streamId;
this.Created = created;
this.Item = item;
}
// Plus implementations of IComparable, IEquatable, etc.
}
When you want to create an F# record, the F# compiler emits a call to this constructor, supplying values for all fields.
For example, the select part of your query would look in C# like this:
select new Envelope<QuestionnaireEvent>(
event.Id, streamId, event.Timestamp,
JsonConvert.DeserializeObject<QuestionnaireEvent>(event.Payload) )
Entity Framework limitations
It so happens that Entity Framework does not allow calling non-default constructors in queries. There is a good reason: if it did allow it, you could, in principle, construct a query like this:
from e in ...
let env = new Envelope<E>( e.Id, ... )
where env.Id > 0
select env
Entity Framework wouldn't know how to compile this query, because it doesn't know that the value of e.Id passed to the constructor becomes the value of the property env.Id. This is always true for F# records, but not for other .NET classes.
Entity Framework could, in principle, recognize that Envelope is an F# record and apply the knowledge of the connection between constructor arguments and record properties. But it doesn't. Unfortunately, the designers of Entity Framework did not think of F# as a valid use case.
(fun fact: C# anonymous types work the same way, and EF does make an exception for them)
How to fix this
In order to make this work, you need to declare Envelope as a type with default constructor. The only way to do this is to make it a class, not a record:
type Envelope<'T>() =
member val Id : Guid = Guid.Empty with get, set
member val StreamId : Guid = Guid.Empty with get, set
member val Created : DateTimeOffset = DateTimeOffset.MinValue with get, set
member val Item : 'T = Unchecked.defaultof<'T> with get, set
And then create it using property initialization syntax:
select Envelope<_>( Id = event.Id, StreamId = streamId, ... )
Why does moving the select to a Seq.map work
The Seq.map call is not part of the query expression. It does not end up as part of the IQueryable, so it does not end up compiled to SQL by Entity Framework. Instead, EF compiles just what's inside query and returns you the resulting sequence, after fetching it from SQL Server. And only after that you apply Seq.map to that sequence.
The code inside Seq.map is executed on CLR, not compiled to SQL, so it can call anything it wants, including non-default constructors.
This "fix" comes with a cost though: instead of just the fields you need, the whole Event entity gets fetched from DB and materialized. If this entity is heavy, this may have a performance impact.
Another thing to watch out for
Even if you fix the problem by making Envelope a type with default constructor (as suggested above), you'll still hit the next problem: the method JsonConvert.DeserializeObject can't be compiled to SQL, so Entity Framework will complain about it, too. The way you should do it is fetch all fields to the CLR side, then apply whatever non-SQL-compilable transformations you need.
Using LINQ to Entities, everything that happens in the query computational expression is actually executed within the database engine, which may reside on a remote server. Everything outside of it is executed in the running application on the client.
So, in your first snippet, Entity Framework refuses to execute Envelope<'T>'s constructor because, in order to do so, it would need to translate that into SQL commands for the server. This is plainly not something it can guarantee, because the constructor could potentially contain any sort of side effects and .NET framework code - it could request user input, read files from the client's hard disk, whatever.
What EF can do, in your second snippet, is sending its own POCO event objects back to the client, which is then tasked with Seq.mapping them to your fancy Envelopes, which it can do because it's running on your client machine with access to the full .NET framework.
Addendum: So why are parameterless constructors ok? What if I were to call MsgBox() in a parameterless constructor? I think that parameterless constructors work by having the client construct the objects (without knowing the query results), sending them to the server in serialised form, and having the server just fill the object's properties with the query results.
I haven't actually tested that. But F# record types have no parameterless constructors anyway, so the point is moot in your case.

Linq to select top 1 related entity

How can I include a related entity, but only select the top 1?
public EntityFramework.Member Get(string userName)
{
var query = from member in context.Members
.Include(member => member.Renewals)
where member.UserName == userName
select member;
return query.SingleOrDefault();
}
According to MSDN:
"Note that it is not currently possible to filter which related entities are loaded. Include will always bring in all related entities."
http://msdn.microsoft.com/en-us/data/jj574232
There is also a uservoice item for this functionality:
http://data.uservoice.com/forums/72025-entity-framework-feature-suggestions/suggestions/1015345-allow-filtering-for-include-extension-method
The approach to use an anonymous object works, even though it's not clean as you wish it would be:
public Member GetMember(string username)
{
var result = (from m in db.Members
where m.Username == username
select new
{
Member = m,
FirstRenewal = m.Renewals.FirstOrDefault()
}).AsEnumerable().Select(r => r.Member).FirstOrDefault();
return result;
}
The FirstRenewal property is used just to make EF6 load the first renewal into the Member object. As a result the Member returned from the GetMember() method contains only the first renewal.
This code generates a single Query to the DB, so maybe it's good enough for You.

Paging and sorting Entity Framework on a field from Partial Class

I have a GridView which needs to page and sort data which comes from a collection of Customer objects.
Unfortunately my customer information is stored separately...the customer information is stored as a Customer ID in my database, and the Customer Name in a separate DLL.
I retrieve the ID from the database using Entity Framework, and the name from the external DLL through a partial class.
I am getting the ID from my database as follows:
public class DAL
{
public IEnumberable<Customer> GetCustomers()
{
Entities entities = new Entities();
var customers = (from c in entities.Customers
select c);
//CustomerID is a field in the Customer table
return customers;
}
}
I have then created a partial class, which retrieves the data from the DLL:
public partial class Customer
{
private string name;
public string Name
{
if (name==null)
{
DLLManager manager = new DLLManager();
name= manager.GetName(CustomerID);
}
return name;
}
}
In my business layer I can then call something like:
public class BLL
{
public List<Customer> GetCustomers()
{
DAL customersDAL = new DAL();
var customers = customersDAL.GetCustomers();
return customers.ToList();
}
}
...and this gives me a collection of Customers with ID and Name.
My problem is that I wish to page and sort by Customer Name, which as we have seen, is populated from a DLL. This means I cannot page and sort in the database, which is my preferred solution. I am therefore assuming I am going to have to call of the database records into memory, and perform paging and sorting at this level.
My question is - what is the best way to page and sort an in-memory collection. Can I do this with my List in the BLL above? I assume the List would then need to be stored in Session.
I am interested in people's thoughts on the best way to page and sort a field that does not come from the database in an Entity Framework scenario.
Very grateful for any help!
Mart
p.s. This question is a development of this post here:
GridView sorting and paging Entity Framework with calculated field
The only difference here is that I am now using a partial class, and hopefully this post is a little clearer.
Yes, you can page and sort within you list in the BLL. As long as its fast enough I wouldn't care to much about caching something in the session. An other way would be to extend your database with the data from you DLL.
I posted this question slightly differently on a different forum, and got the following solution.
Basically I return the data as an IQueryable from the DAL which has already been forced to execute using ToList(). This means that I am running my sorting and paging against an object which consists of data from the DB and DLL. This also allows Scott's dynamic sorting to take place.
The BLL then performs OrderBy(), Skip() and Take() on the returned IQueryable and then returns this as a List to my GridView.
It works fine, but I am slightly bemused that we are perfoming IQueryable to List to IQueryable to List again.
1) Get the results from the database as an IQueryable:
public class DAL
{
public IQueryable<Customer> GetCustomers()
{
Entities entities = new Entities();
var customers = (from c in entities.Customers
select c);
//CustomerID is a field in the Customer table
return customers.ToList().AsQueryable();
}
}
2) Pull the results into my business layer:
public class BLL
{
public List<Customer> GetCustomers(intint startRowIndex, int maximumRows, string sortParameter)
{
DAL customersDAL = new DAL();
return customersDAL.GetCustomers().OrderBy(sortParameter).Skip(startRowIndex).Take(maximumRows).ToList();
}
}
Here is the link to the other thread.
http://forums.asp.net/p/1976270/5655727.aspx?Paging+and+sorting+Entity+Framework+on+a+field+from+Partial+Class
Hope this helps others!

Inserting and updating disconnected entities in EF code first

I am retrieving data about books from lots of different sources such as XML and web services which I then store in the database using EF Code First 6 via a Generic Repository and and obviously DbContext.
The problem is that performance is very bad.
I have the following (fictional but analogous) POCO in my Model
public class Book
{
public int Id {get; set;}
public string Title {get; set;}
}
also
public class BookDataSource
{
public int Id {get; set;}
public virtual List<Book> Books {get; set;};
}
So I retrieve the book data from some source and construct the above book object.
I then need to check whether the book already exists in the DB and update it if it does or insert it if it does not. I also need to then delete any books that no longer exist on the data source.
//The following method takes the data source (type: IBookDataSource) to update from as the parameter
public string UpdateBooks(BookDatasource dataSource)
{
string successMessage = "";
//Disconnected entities
List<Book> retreivedBooks= dataSource.RetreiveBooks();
foreach (Book retreivedBook in retreivedBooks)
{
//Check if the dataSource already contains a book (based on title)
Book localBook =
dataSource.Books.SingleOrDefault(
b => b.Title== retreivedBook.Title);
if (localBook ==null)
{
//Insert a new one
_unitOfWork.BookRepository.Insert(retreivedBook);
}
else
{
//Update existing
localBook.Title= retreivedPortalMerchant.PortalsMerchantName;
_unitOfWork.PortalMerchantRepository.Update(localPortalMerchant);
}
}
//Soft delete any existing ones that no longer exist in the received data
foreach (Book existingBook in dataSource.Books)
{
if ( !retreivedBooks.Exists(
b => m.Title == existingBook.Title))
{
existingBook.Deleted = true;
_unitOfWork.PortalMerchantRepository.Update(existingBook);
}
}
}
However the performance is very bad. Sometimes there are 25000 books retrieved from the data source and I am having to do two for loops. ForEach retreived book, check if one exists in the db the insert/update accordingly. And another one to loop all existing books and check whether it no longer exists on the datasource and soft delete.
Is there a better way to attach the entities and monitor their state. In the above example I think I am querying the context each time and not the DB so why such bad performance. Should I revert to T-SQL?
For the proper algorithm of inserting-updating-deleting disconnected entities, you can check "Setting the State of Entities in a Graph" section of "Chapter 4. Working with Disconnected Entities Including N-Tier Applications" of "Programming Entity Framework: DbContext by Julia Lerman, Rowan Miller" book.
Also in this SO answer some ways to increase performance of EF is explained. The answer is for bulk inserting however it may work for your scenerio also.
The fastest way would be using bulk insert extension
Here's maxlego's description:
It uses SqlBulkCopy and custom datareader to get max performance. As a result it is over 20 times faster than using regular insert or AddRange EntityFramework.BulkInsert vs EF AddRange
context.BulkInsert(hugeAmountOfEntities);

Is it possible to manipulate SOME entities in a ServiceOperation returning an IQueryable

I have a ServiceOperation to query items available to a certain user at a certain time.
In short this methode does:
var fullResult = from i in Items where ... select i; //get ALL possible items where...,
Lets say this returns items {A, B, C, D}.
A second query filters out which of those items the calling user has access to.
var clientResult = from ci in fullResult where (privilege's and schedule's are true)
This mite result in {A, C } and is returned.
The result on the client side is: only the list of items the client has access to is displayed. This can be annoying since you don't know if you made a mistake in searching, or the item is just not available right now.
What I would like to be able to do is show all possible results to the client {A, B, C, D} yet FLAG B and D in this case as unavailable.
My entity has already a property isReadOnly I could use.
Can I write a query to not just filter out, but also flag any remaining results as read only? An ideal result would be {A, B.isREadOnly=true, C, D.isReadOnly=true}
Or did I reach the limit of what is doable and do I have to write a traditional WCF web method, creating a separate class, returning a list of results?
PS: this 'isReadOnly' property is only used for this, I don't mind it being changed in the DB at all
Thanx for any pointers
Andreas
If I were you I would consider not returning the entity directly out of your service and instead map it to something that has the ReadOnly property. For example, if your entity is:
public class A
{
public string Name { get; set; }
}
Then you could have a data contract like this:
[DataContract]
public class AExtra
{
[DataMember]
public string Name { get; set; }
[DataMember]
public bool IsReadOnly { get; set; }
}
what this means is that you could do this in your query:
var res = from a
in Items
where (...whatever your original logic is)
select new AExtra
{
Name = a.Name,
IsReadOnly = (...put your logic for determining ReadOnly in here)
};
And then return res from your service operation.
Just an opinion really but I like to do things like this rather than send the entities directly out of the service - it always gives me a bit more freedom to change things without having too many knock-on effects.