Entity Framework 4.1 DbContext Extending Partial Classes - entity-framework

Building a C# application using EF 4.1 with Database First. My question centers around using extension methods to return values through the DbContext object.
My entities were created as partial classes by the DbContext generator. I have a Projects table and a related Managers table and through the context object I can perform LINQ queries and access projects and the assigned project manager. If the Manager table has firstname and lastname fields how would I write my extension as a property or method to concatenate the first and last name fields so that when I query for a project and use the manager relation the property FullName returns the combined value?
This example has a variable _projects populated with a list of Projects created using LINQ query:
Fields["manager"].Value = _projects[i].Project.ProjectManager.FullName
I can makethe FullName property into a method and pass the id for the manager however wouldn't that make it into an additional query? Thanks for the help.

If you know that you're always going to be accessing the ProjectManager navigation property, you can include it in the initial query by using the Include method
var projects = (from p in ctx.Projects
select p)
.Include(p => p.ProjectManager)
.ToList();
Then you can add the following property to your Manager class (in a seperate file than the generated one)
public string FullName
{
get { return FirstName + " " + LastName; }
}
And access it using
var manager = projects[0].ProjectManager.FullName;
If I missinterpreted your question, could you provide an example of what your code would look like using your proposed extension method?

Related

AutoMapping stored procedure results

I'm wondering if there is any way to map a stored procedure result into into a class.
This is what I have:
// DbContext Class:
public DbSet<StoredProcedureModelResult> SPMR { get; set; }
// Service Class:
var result = ctx.Set<StoredProcedureModelResult>().FromSql("getXXXX p1 = {0},1).ToList();
This works well, however, I'm using database migrations and every time I add one this thing creates StoredProcedureModelResult as a table...
I tried to ignore it onModelCreating:
modelBuilder.Ignore<SPModels.test>();
but this throws an exception:
Cannot create a DbSet for 'StoredProcedureModelResult ' because this type is not included in the model for the context
I just want use the benefit of mapping, and not to get a table creation, this is a simple model (non-entityType)
BTW
.NET Core 1.1
Web API
EF Core (code-first)
Thank you
You don't need to make the type an Entity type (by registering a DbSet in your DbContext). Just have a method that returns IEnumerable<StoredProcResults> (can be in your DbContext), and in it run
dbContext.Database.SqlQuery<StoredProcResults>(...)
See Database.SqlQuery<T>(...)

add my own property to EF designer

I using vs2010 and the built-in EF designer against SQL server Compact 4.0 local database that in my project. ( design-first)
I tried to add (through the designer) to one of the entities a new property that doesn't exist in the DB (nor planed to) by: add-new scalar property.... , but when i was tring to validate it, i got an error:
property "x" is not map
my question:
can i add my own properties to the schema through the designer. and that properties won't be exist in the underline DB.(I thought i could)?
if I can, how?
You can add non db fields to your entity by creating a partial class of that entity with the required properties. These won't be used for the ORM.
public partial class MyEntity {
public string StringStatusCode { get;set;}
}

Combine columns in entity framework into one column with the edmx designer

I'm using EntityFramework 5 EDMX designer and would like to combine the first & last name of a person into a single field value (name, for instance) on the entity.
I thought in previous versions there was a way to do this, but I don't see anything available to do what I need to do.
Is this still possible?
Unless I'm not understanding your question, I believe I've done that with a partial class that resembles something like the following:
public partial class person
{
public string name {
get
{
return firstname + " " + lastname;
}
set{ }
}
}
No it is not possible. You can create model defined function and use it in queries but it will still not be part of your entity. If your entity is read only you can create database view with combined column and map it instead of the table - it shows also main reason why combining columns into single property is not such easy task. Automatic concatenating during reading is easy but automatic decomposing to save correct value into correct column is hard and error prone.
If you need combined property for anything else than querying you can simply create another partial part of your entity class and add your own computed property. If you need the combined property for querying use the model defined function.
The way I do this is through a Computed Column as explained here:
How to make a computed column nullable in SQL Server
If you use a computed column you'll be able to use such a column in your LINQ queries. For example:
var users = Database.Users.Where(u => u.FullName.ToLower().Contains("string"));
You won't get errors like "not supported in LINQ to Entities" because this property is really a part of your model object. All the heavy lifting occurs on the database side.
Of course you could place a FullName property in a partial class and use it.
public string FullName
{
get { return string.Format("{0} {1}", FirstName, LastName); }
}
In this case, you'll have to call .ToList() first ( Database.Users.ToList(); ) to be able to use this property in LINQ queries. .ToList() will hydrate/bring all your Users to memory. This is not desirable!
You can also try the FullName property implementation that's described here: Calculated Columns in Entity Framework Code First Migrations

Using Include() with inherited entities

In EF eager loading related entities is easy.
But I'm having difficulties including inherited entities when loading data using table-per-type model.
This is my model:
Entities:
ArticleBase (base article entity)
ArticleSpecial (inherited from ArticleBase)
UserBase (base user entity)
UserSpecial (inherited from UserBase)
Image
Relations are as shown on the image (omitting many columns):
In reality my users are always of type UserSpecial, since UserBase is used in another application, thus we can share credentials. That's the only reason I have two separate tables. UserBase table can't be changed in any way shape or form, because the other app would break.
Question
How am I suppose to load ArticleSpecial with both CreatedBy and EditedBy set, so that both are of type UserSpecial (that defines Image relation)?
I've tried (unsuccessfully though) these options:
1.
Using lambda expressions:
context.ArticleBases
.OfType<ArticleSpecial>()
.Include("UserCreated.Image")
.Include("UserEdited.Image");
In this case the problem is that both CreatedBy and EditedBy are related to UserBase, that doesn't define Image navigation. So I should somehow cast these two to UserSpecial type like:
context.ArticleBases
.OfType<ArticleSpecial>()
.Include("UserCreated<UserSpecial>.Image")
.Include("UserEdited<UserSpecial>.Image");
But of course using generics in Include("UserCreated<UserSpecial>.Image") don't work.
2.
I have tried using LINQ query
var results = from articleSpecial in ctx.ArticleBase.OfType<ArticleSpecial>()
join created in ctx.UserBase.OfType<UserSpecial>().Include("Image")
on articleSpecial.UserCreated.Id equals created.Id
join edited in ctx.UserBase.OfType<UserSpecial>().Include("Image")
on articleSpecial.UserEdited.Id equals edited.Id
select articleSpecial;
In this case I'm only getting ArticleSpecial object instances without related properties being set. I know I should select those somehow, but I don't know how?
Select part in my LINQ could be changed to something like
select new { articleSpecial, articleSpecial.UserCreated, articleSpecial.UserEdited };
but images are still not loaded into my context. My joins in this case are barely used to filter out articleSpecial results, but they don't load entities into context (I suppose).
This seems to be a limitation in the current version of Entity Framework (1.0) Have a look at this related SO question.
In your case including the related UserCreated and UserEdited properties in the projection is the right solution. However if you also want to populate the Image property on the UserSpecial object, you must be sure to include that as well:
var results = from articleSpecial in ctx.ArticleBase.OfType<ArticleSpecial>()
select new
{
articleSpecial,
articleSpecial.UserCreated,
((UserSpecial)articleSpecial.UserCreated).Image,
articleSpecial.UserEdited,
((UserSpecial)articleSpecial.UserEdited).Image
};
Of course this query builds on the assumption that all ArticleSpecial entities always refer to a UserSpecial entity, otherwise the casting will fail.
If this assumption isn't always true, you could express the same query using the LINQ extension methods and a multi-line lambda function to perform a safe casting:
var results = ctx.ArticleBase
.OfType<ArticleSpecial>()
.AsEnumerable()
.Select(a =>
{
var userCreated = a.UserCreated as UserSpecial;
if (userCreated != null)
{
var image = userCreated.Image;
}
var userEdited = a.UserEdited as UserSpecial;
if (userEdited != null)
{
var image = userEdited.Image;
}
return a;
});
In the latter example, you also do not need to include UserSpecial and Image entities in the results. Instead you just need to access the navigation properties on the ArticleSpecial entities during the projection phase in order to force Entity Framework to eager load the related objects.

How do I get Entity Framework to use interfaces on the generated classes?

I have a project where the client is using Entity Framework, and I'm trying to abstract away the generated classes from the rest of the application.
One generated class is Category and it has say Type as a property.
I've created an interface that I want Category to implement, like this:
public interface ICategory
{
string Type { get; set;}
}
I have done this in LINQ to SQL before and it works fine. I create a partial class in a separate file and have it implement the interface:
public partial class Category: ICategory
//implement interface
However, with EF whenever I try to build a query with EF it says it doesn't support OfType<>().
Example:
var query = from c in DataContext.Category
where Type == "some type"
select c;
var resultsList = query.OfType<ICategory>(); //error here (not supported)
What am I doing wrong here?
Other things to note: I'm developing this in a silverlight application and the data context is actually being pulled from a service, so there's a client server relationship going on here as well.
As a general rule, LINQ to Entities can only understand things which are part of your entity model (EDMX). So while you are free to extend your entity types be a partial classes, you cannot use properties, methods, and interface references you add there in LINQ to Entities queries, except for certain, very specific features.
However, in this case the following query should give you the result you want:
var resultsList = query.Select<ICategory>(c => c);