How to include only a single property when using 'expand' - breeze

I have an orders table which I want to query. One of the properties is "UserId" and which turns into a navigation property to the User.
I can query this to get the order and the associated User. However, I don't want the entire User entity, only the UserName property.
How do I construct that query in breeze?
Something like:
let query = new breeze.EntityQuery()
.from("orders")
.expand("user.userName");
I tried this, but then returned objects are not actually entities, but it does return just the userName:
let query = new breeze.EntityQuery()
.from("cases")
.select("field1, field2, user.userName");
Is there any other way of doing this? Note that I am using EF on the backside.

The best solution I found for this is creating a "virtual entity" which consists of just the two fields that I want. In other words, I have AspNetUsers as one table with it's corresponding entity. And then I have a second code first entity which consists of only the Id, and the UserName:
[Table("AspNetUsers")]
public partial class User
{
[Key]
[Column("Id")]
public string AspNetUserId { get; set; }
[StringLength(256)]
public string UserName { get; set; }
}
I can then use it as a relation in other tables and include it like was just another table.

Related

Entity Framework Mapping. Multiple Foreign keys

I have two tables
People Relation
------------- -----------------
Id (int) Id (int)
Name (string) ParentPeopleId (int)
ChildPeopleId (int)
I need to get all people by Relation table with union all.
The relation table has two foreign keys. And there is one problem with mapping them. The mapping is one to many. People has many Relation, Relation has one People.
I mapped them like this:
HasRequired(r=> r.People).WithMany(p=>p.Relation).HasForeignKey(r=>r.ChildPeopleId);
So, how can I map the second foreign key?
Per each FK column in your Relations table you should have a navigation property in your Relation entity (this is not mandatory, but what is mandatory is have at least one navigation property between the entities involve in the relationship). In this case you have two relationships between People and Relations, and a navigation property represents one end in an relationship. Your model could be this way:
public class Relation
{
public int Id {get;set;}
public int ParentPeopleId {get;set;}
public int ChildPeopleId {get;set;}
public virtual People ParentPeople {get;set;}
public virtual People ChildPeople {get;set;}
}
public class People
{
public int Id {get;set;}
public string Name {get;set;}
public virtual ICollection<Relation> ParentRelations {get;set;}
public virtual ICollection<Relation> ChildRelations {get;set;}
}
And the Fluent Api configurations like this:
HasRequired(r=> r.ParentPeople ).WithMany(p=>p.ParentRelations ).HasForeignKey(r=>r.ParentPeopleId);
HasRequired(r=> r.ChildPeople).WithMany(p=>p.ChildRelations ).HasForeignKey(r=>r.ChildPeopleId );
Now if you don't want to work with one of the collection navigation properties in your People entity, you can create an unidirectional relationship. For example if you don't want ParenRelations navigation property, you can configure that relationship as follow:
HasRequired(r=> r.ParentPeople).WithMany().HasForeignKey(r=>r.ParentPeopleId);
Update
Let me start first with a suggestion. I thing your table Relation is not playing any role is you have only those columns. If a person con only have a parent I would change your model to the following:
public class People
{
public int Id {get;set;}
public string Name {get;set;}
public int ParentId {get;set;}
public virtual People Parent {get;set;}
public virtual ICollection<People> Children {get;set;}
}
And you relationship configuration would be:
HasOptional(r=> r.Parent).WithMany(p=>p.Children).HasForeignKey(r=>r.ParentId);
Now going back to your current model, EF sees your ChildPeopleId property as an simple scalar column, it doesn't know it's a FK column, that's way I suggested above map two relationship instead one.
Another thing, with the below line
var Peoplelist = MyDbContext.People.Include(p=>p.Relations.Select(r=>r.People)).ToList();
You are telling to EF that you want to load the Relation entities related to a People, but also you want to load the People related with each Relation, which is at the same time the same People where the Relation came from, so, you don't need to do the last select, if your data is properly related, that People navigation property is going to be loaded when you execute your query,so, that query should be this way:
var Peoplelist = MyDbContext.People.Include(p=>p.Relations).ToList();

How to query existing table when using code first in entity framework

I am using Entity Framework 6 Code First. I created a separate table to contain the UserId from the aspnet_Users table and a field for Department. So the user listed with the departments have only access to those departments.
Since all of my table are generated via code first and is using the db.context. The membership and roles are pre-generated table from MVC. How to I get a list of UserId from the aspnet_Users table when it's not in the db.context? The aspnet tables are pre-generated via a script in the entity framework.
How do I query tables in MVC outside of my db.context?
Your DbContext will have a Database property. Off of that you will find two overloads for general SQL queries:
DbRawSqlQuery SqlQuery (Type elementType, string sql, params object[] parameters);
DbRawSqlQuery<T> SqlQuery<T>(string sql, params object[] parameters);
For example:
var result = ctx.Database.SqlQuery<Foo>("select * from foo");
More information here
Since you are using .Net Membership, you could always call the
MembershipProvider.GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
Then from that result, generate a list of UserIds. The role provider also offers similar functionality with a Roles.GetAllRoles() method.
The membership provider and role provider offer many more useful methods to hopefully get you the data you are looking for. If they still don't have what you are after you have a couple of more options. You can use your db context to execute raw SQL. See MSDN for more info.
Another option is to create additional entity classes that match the DB structure of those tables, and add them to your DB Context. The downside to this approach is it could allow another developer, or even yourself to create and update users and roles without going through the proper providers, in which case you would lose some functionality. If that is a concern, you could always create a DB View and map to that to ensure read only access. It's a bit more overhead, but does give you type safety and a familiar way to query the data.
Here is what I did to get the complete solution I wanted:
To query the data:
string sql = "Select UserId, UserName from aspnet_users where applicationid='" + Config.Instance.AppId() + "'";
using (var context = new NameSystemContext())
{
var users = context.Database.SqlQuery<AspnetUser>(sql);
ViewBag.UserId = new SelectList(users, "UserId", "UserName").ToList();
}
In your view models or somewhere define a class:
class AspnetUser
{
[Key]
//[Column(Order = 1)]
public Guid UserId { get; set; }
//[Key]
//[Column(Order = 2)]
public string UserName { get; set; }
}
//ViewBag.UserId could be use in the view
#Html.DropDownList("UserId", null, "Select...", htmlAttributes: new { #class = "form-control" })

If you are using Entity Framework, how to do you use the EF Model classes instead of having to make custom View Models?

I am new to MVC. If one imports all of their existing tables in a database, they can created Entity Framework models. My question is, how do I actually use these models instead of having to fall back on creating custom View Models of the table data? Here is what I mean:
My understanding is that model classes that Entity Framework automatically generates should not be modified (example: a model of a Products table). Because of this, I have to create a whole new View Model of the Products table in order to be able to add things like [Display] and [Required] tags to the model so that I can have a custom name displayed to the user (e.g. "Store Products") and validation (e.g. the product name field is required).
See what I mean? Do you always have to manually create a View Model in order to get needed functionality like validation and user-understandable display names?
Side question: the models that Entity Framework automatically creates (based on your existing tables in the database) are called "Domain Models" right?
If the only reason you want to make separate view model is because you want to add data annotations then you can just use partial classes
eg: Given an EF generated class
public partial class MyClass
{
public int Id { get; set; }
public string SomeText { get; set; }
}
you can add a new file with:
[MetadataType(typeof(MyClassMetadata))]
public partial class MyClass
{
}
public class MyClassMetadata
{
[Required]
[Display(Name = "An Id")]
public int Id { get; set; }
[AllowHtml]
[Display(Name = "Some HTML text")]
public string SomeText { get; set; }
}
to decorate your EF classes.
Yes, this looks a bit clunky. There might be a neater way to do this in the newer versions.

single entity for different tables

I have same type of tables
ProductCodeTable, CountrycodeTable etc
All have key, value as their fields
When I use entity frame work,
Can I have a single entity for all these tables such that I can formulate different queries to get data from different tables?
You can create a base class for all of them and create sub class for each entity
public abstract class LookUpEntity
{
[Key]
public int Key { get; set; }
[Required]
public string Value { get; set; }
}
[Table("ProductCodeTable")]
public class ProductCode : LookUpEntity
{
}
This way you can model the relationships also and later if you wanted to add specific properties to those look up entities with out affecting other entities.
You can create a view with a Union of all tables like this:
create view AllKeyTables as
SELECT 'Product' as table, Productkey as Key, nameProduct as name
FROM ProductCodeTable
UNION
SELECT 'Country' as table, CountryISO as key, CountryName as name
FROM CountrycodeTable
UNION
...
Then update EF model and check 'table' and 'key' fields as Entity Primary Key.
Next question you will do is: 'How can I make a relation between this Entity and existing Entities?' The answer is 'you can't because EF is not able to join Entities between other fields than primary key'. Then, before implement this solution, be sure that this is you are looking for.
EF supports this only if you model it as inheritance (#Eranga showed it in code-first approach). You will have single base entity and derived entity for each table so you will not avoid having different type for each table. Otherwise the answer is no.
Inheritance will put additional requirements on data in your tables. For example Ids will have to be unique among all tables. So if ProductTableCode will have record with Id 1, CountryCodeTable (and any other code table) mustn't have record with Id 1.
Also inheritance in EF can produce nasty and very poorly performing queries.

How can I reuse Model Metadata for custom View Models?

I'm working on an ASP.NET MVC 2 project with some business entities that have metadata dataannotations attributes applied to them (Validation attributes, Display attributes, etc.).
Something like:
//User entity
public class User
{
[DisplayName("Vorname")]
[Required(ErrorMessage = "Vorname fehlt")]
[StringLength(MaxNameLength, ErrorMessage = "Vorname ist zu lang")]
public string FirstName { get; set; }
[DisplayName("Nachname")]
[Required(ErrorMessage = "Nachnamefehlt")]
[StringLength(MaxNameLength, ErrorMessage = "Nachname ist zu lang")]
public string LastName { get; set; }
[Required]
public string Password{ get; set; }
}
Using the metadata from different views is no problem, as long as I am using my business entities as viewmodels or as part of a viewmodel like this:
//custom viewmodel with a user entity
public class CustomViewModel
{
public User{get;set;}
//some more properties...
}
However, sometimes I need to code a view for editing some, but not all fields of an entity. For those fields I want to reuse the metadata already specified in my user entity. The other fields should be ignored. I'm talking about custom view models like this:
[MetadataType(typeof(User))]
public class UserNameViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
//no password on purpose, the user should only
//edit his first and last name in this view
}
That's where I am running into problems. The custom view model above leads to an exception when the view is generated, because it has no password property.
The associated metadata type for type
'Zeiterfassung.Models.ViewModels.Users.UserNameViewModel+UserModel'
contains the following unknown
properties or fields: Password. Please make sure
that the names of these members match
the names of the properties on the
main type.
Also, even if this exception did not occur, I expect to get into even more trouble with model validation on form submit because Password is marked as required in my business entity.
I can think of several workarounds, but none seem really ideal. In any case I can't change the database layout so that the password field would be in a separate entity in my example above.
How would you handle this scenario?
The only recommendation I could give you is to have view models specific to each view and have only the necessary properties and validation attributes on those view models. Don't worry if you repeat some validation attributes and properties on your view models. That's what they are meant for: reflect the logic of a given view.

Resources