Create a BreezeJs EntityType that is not in EntityFramework - breeze

I have a Web API 2 service that has a Breeze Controller that connects to entity framework. It gets several EntityTypes from tables in my database (like Employee, UserConfiguration, Shipment etc)
It all works great.
But now I want to make a "custom" EntityType. One called User. I don't actually have a User table in my database. I am using a few different sources to make an instance of User. (Employee Table, UserConfiguration Table and a Service Call)
When I make the call to my GetCurrentUser method, the data is returned correctly to the client.
But I have this setup to allow my constructor to be called when breeze creates the object:
metadataStore.registerEntityTypeCtor('User', Entities.User, this.setupEntity);
But the constructor never gets called.
How can I make it see the User entity?
Note: If possible, I would prefer to set this up in my Web API code, rather than in my JavaScript/TypeScript.
In case it is relevant, here is part of my User class:
[DataContract]
public class User
{
public User(Employee employee, ApplicationPermission permissions,
UserConfiguration userConfiguration)
{
EmployeeId = employee.EmployeeId;
LanId = employee.LanId;
FirstName = employee.FirstName;
LastName = employee.LastName;
UserPermissions = new List<UserPermission>();
UserConfiguration = userConfiguration;
}
[DataMember]
int? EmployeeId { get; set; }
[DataMember]
string FirstName { get; set; }
[DataMember]
string LastName { get; set; }
[DataMember]
List<UserPermission> UserPermissions { get; set; }
[DataMember]
private UserConfiguration UserConfiguration { get; set; }
}

I was able to get this to work by adding my custom class to the Entity Framework model (even though it does not have a table). I think it was easier with the a code model. I don't know if it would have been doable with a design model (edmx).
This link got me started:
http://breeze.github.io/doc-js/metadata-with-ef.html

Related

Populating a Lazy<T> collection

I am trying to get my head around lazy loading in an ASP.Net MVC app. For instance, I have a class with a property that is a collection (Employees). I want the collection to only load when I need it loaded:
public class Department
{
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int DepartmentId { get; set; }
public string DepartmentName { get; set; }
[ForeignKey("DepartmentId")]
public Lazy<ICollection<Employee>> Employees { get; set; }
}
First, I am not sure if I should lazy load the class or the collection
public Lazy<ICollection<Employee>> Employees { get; set; }
public ICollection<Lazy<Employee>> Employees { get; set; }
I assume the collection.
Next, I cannot seem to find a related example to actually load the property/collection once I need it and after the class has been instantiated. I am also not sure if this is done in the class itself or in my MVC controller.
Any help is appreciated.
You don't have to use the Lazy<T> on your Employees property. You'll just be adding unnecessary "lazyness", since Entity Framework (and other ORMs like NHibernate) queries are already lazy, i.e.: the query will only hit the database when you explicitly tell it to.
So, by making Employees of type:
public virtual ICollection<Employee> Employees { get; set; } //make sure to mark it as virtual, otherwise it won't be lazy
When querying:
var result = myContextObj.Departments.Include(d=> d.Employees).Where(d=> d.Id == someID).SelectMany(d=> d.Employees);
The code above does nothing but create a Query Object representing the query that may be sent to the database.But it's not going to do anything, unless you "materialize" the result, either by doing a foreach on result, or calling ToList() for example.
For lazy loading you must:
public virtual ICollection<Lazy<Employee>> Employees { get; set; }. You actually miss the virtual that allows the framework to create the proxy by overwritting the property;
context.Configuration.ProxyCreationEnabled = true;, this is the defautl value.

MVC CodeFirst one to many relationship creates new data

I'm using CodeFirst with MVC 3 and have these two classes:
public class Person
{
public int PersonId { get; set; }
[Email]
[Required]
public string Email { get; set; }
public string Passwort { get; set; }
public virtual City City { get; set; }
}
public class City
{
public int CityId { get; set; }
[Required]
public string Name { get; set; }
public virtual IEnumerable<Person> Persons { get; set; }
}
When adding a new person I want to reference a city to this person. Therefore i'm using a SelectList with all cities in my view. The CityId and the object is transferred correctly to the Post-method, but when saving the changes to the database I will have a new object in the city-table (with same name, but new Id).
I suggest there's something wrong with the relations in my models. Maybe somebody can help me.
If you give your Person model an explicit CityId property, then you won't need to retrieve the City object from your repository, you can just assign the CityId value directly to the Person object and save it. For really straightforward views, you don't need to use a viewmodel either, you could receive a Person instance into the POST action method and CityId would already be assigned, assuming the html field in the View has the same name.
This should fix your problem, because you will then know you are explicitly using a CityId that already exists.
Your database will already contain a Person.City_CityId field anyway so you're not creating anything new, just giving yourself more control over the situation. Sometimes you may need to use a [ForeignKey] attribute in the model to connect the Person.CityId property with the virtual property, but using the standard naming convention this shouldn't be necessary.

Establish Foreign Key Connection Using Entity Framework With SQL Queries

I have a couple of classes (for this example anyway) that use code first with the entity framework to connect to the database.
public class Customer
{
[Key]
public long CustomerId { get; set; }
public string CompanyName { get; set; }
...
public virtual List<Contact> Contacts { get; set; }
}
public class Contact
{
[Key]
public long ContactId { get; set; }
public string Forename { get; set; }
...
public long CustomerId { get; set; }
public virtual Customer Customer { get; set; }
}
When I hook these up in my context class directly to the db the foreign key relationships hook up fine and I can access the collection of contacts from within the customer class.
class RemoteServerContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
public DbSet<Contact> Contacts { get; set; }
...
}
My problem is that these database tables are used by various different systems and are massive. In order to increase efficiency I have overridden the default behaviour to point at a view (and also a stored proc elsewhere) rather than directly at the table.
public IEnumerable<Customer> Customers ()
{
return Database.SqlQuery<Customer>("SELECT * FROM vw_CustomerList");
}
public IEnumerable<Contact> Contacts()
{
return Database.SqlQuery<Contact>("SELECT * FROM vw_ContactsList");
}
I have made sure that in each of the views I have included the foreign key fields: CustomerId and ContactId.
When I do this however the class joins appear to be lost - there's always a null when I drill into either of the objects where it should be pointing to the other one. I have tried to set up what the foreign key field should point to but this doesn't seem to help either.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Contact>().HasRequired(p => p.Customer)
.WithMany()
.HasForeignKey(k => k.CustomerId);
}
Is there a way to establish the connection when overriding the default behaviour?
There is no overriding in this case. If you removed
public DbSet<Customer> Customers { get; set; }
and replaced it with
public IEnumerable<Customer> Customers ()
{
return Database.SqlQuery<Customer>("SELECT * FROM vw_CustomerList");
}
you have completely changed the behavior. The first uses entities and full power of EF. The second is only helper to execute custom SQL. Second without first or without defining entity in OnModelCreating doesn't use Customer as mapped entity at all - it uses it as any normal class (only mapped entities can use features like lazy loading).
Because your Customer is now mapped to view you cannot use your former Customer class used with table. You must define mapping of Customer to a view by cheating EF:
modelBuilder.Entity<Customer>().ToTable("vw_ContactsList"); // EF code fist has no view mapping
Once you have this you can try again using:
public DbSet<Customer> Customers { get; set; }
Unless your view is updatable you will get exception each time you try to add, update or delete any customer in this set. After mapping relation between Customer and Contact mapped to views your navigation properties should hopefully work.
The problem with SqlQuery is the way how it works. It returns detached entities. Detached entities are not connected to the context and they will not lazy load its navigation properties. You must manually attach each Customer instance back to context and to do that you again need DbSet.

Partial update of entity objects with EF 4

I'm implementing DAL and BL layers of application.
It is hosted as WCF service, and EF 4 is used as ORM.
We have role based security layer and business rule that only part of object can be updated by some particular role.
Here is simplified example of problem:
We have such DTOs:
MainType
{
public Guid ID { get; set; }
public String DoctorField1 { get; set; }
public String DoctorField2 { get; set; }
public String NurseField1 { get; set; }
public String NurseField2 { get; set; }
public DateTime Created {get; set;}
public DateTime Updated {get; set;}
public Guid LastUpdateBy {get; set;}
public List<DetailsType> Details { get; set; }
}
DetailsType
{
public Guid MainTypeID { get; set; }
public Guid SomeIdentityID { get; set; }
public String DoctorDetail { get; set; }
public String NurseDetail { get; set; }
public DateTime Created {get; set;}
public DateTime Updated {get; set;}
public Guid LastUpdateBy {get; set;}
}
This entities are mapped to corresponding DB tables with the same fields.
ID field of MainType is Primary Key;
MainTypeID of DetailsType is Foreign Key to MainType table.
SomeIdentityID of DetailsType is FK to some other entity that is not important for this sample.
MainTypeID SomeIdentityID is complex primary key for DetailsType table.
I have graph of such objects (1 main and list details), and determined role of user who performs update operation.
My task is:
IF current user has role Doctor - update Doctor fields in Main object and all Details objects, insert new details objects.
IF current user has role Nurse - update Nurse fields in Main object and all Details objects.
save current date to Updated field
save current user id to LastUpdateBy field
do not modify Created field and any other field that are not updated by this role.
So for example if I have user with role Doctor I should do following:
Update DoctorField1, DoctorField2, Updated, LastUpdateBy in MainObject
Update DoctorDetail, Updated, LastUpdateBy in every details object
DO NOT modify any other fields.
Currently we have implementation that reads full graph for MainObject, makes necessary modifications and saves in back to DB.
This solution works too slow and I need to find a way to improve it.
Currently I know clearly how to do that by RAW SQL, but this will be my solution in case nothing else will help.
How can I make Entity Framework to update only needed fields and ignore another.
I have some successful results with ApplyOriginalValues and ApplyCurrentValues methods for String fields.
Idea was to assign some fictive value to property in both objects, for example string "##$%&##$%&##$%&##$%&##$%&", and EF then treats them as not modified properties during saving changes.
However this trick does not work with Boolean, Int32 and Decimal values.
I should use some simple approach to all objects.
I will appreciate any ideas and thoughts about this problem.
If you have such specific requirement you should start by modifying your WCF service to not accept fields which user cannot modify. That leads to two simple DTOs:
public class MainTypeUpdateDto
{
public Guid ID { get; set; }
public String Field1 { get; set; }
public String Field2 { get; set; }
public List<DetailsTypeUpdateDto> Details { get; set; }
}
public class DetailsTypeUpdateDto
{
public Guid MainTypeID { get; set; }
public Guid SomeIdentityID { get; set; }
public String Detail { get; set; }
}
All other fields either cannot be updated or should be handled by your server side logic.
Now when you receive dtos you can map them back to real entity objects. Based on user role you will know which fields and details you must set. You have two options to force EF to save only fields you want:
First create object graph with MainType and related details. Set only Ids in these entities and attach MainType entity to context. After that set all updatable fields to current values. Do not change state of any entity.
Create object graph with MainType and all related details and set all Ids and all updatable fields. After that attachMainType` entity to the context and manually set state for each modified property (on each entity).
You can need some additional logic if user can also remove or add details.

managing lookup in MVC2 and persisting object with Nhibernate

My simplified domain model looks something like this:
public abstract class Entity<IdK>
{
public virtual IdK Code { get; protected set; }
}
public class Contact : Entity
{
public virtual string Name { get; set; }
public virtual Company Company { get; set; }
}
public class Company : Entity
{
public virtual string Name { get; set; }
}
and I've defined a viewmodel:
public ContactViewModel()
{
public Guid Code { get; set; }
public int Version { get; set; }
public string Name { get; set; }
public string Company { get; set; }
public List<SelectListItem> Companies { get; set; }
}
to manage my contacts in a view.
Since I want the user to be able to choose from a list of companies I've added a list of SelectedListItem which will be rendered in my view like this:
<%=Html.ListBoxFor(m => m.Company, (List<System.Web.Mvc.SelectListItem>)Model.Companies)%>
Now, when the user submits my form I remap my viewmodel with my model before I save it.
I populate my Contact and use the id of the ContactViewModel.Company to create an object of type Company to associate with the property of the Contact class.
Since I don't want to fetch the whole company from the database I just fill the id.
When I persist my contact, though, I get an exception: "not-null property references a null or transient Domain.Contact.Company".
What is the best solution to manage lookups and persistence with MVC + Nhibernate?
Do you have any suggestions from your experience?
Unfortunately with NHibernate and lookups you can't just assign the ID property to a new instance of the Company object and then assign that Company object to the Contact.
Generally what I would do is in my repository, assuming that you can't change the Company information when saving a contact is something like this:
public Contact Save(Contact contact)
{
if(contact.Company.Id > 0)
contact.Company = Session.Load<Company>(contact.Company.Id);
Session.SaveOrUpdate(contact);
}
I generally find this allows you to encapsulate the logic of loading the Company and also allows you to keep it all wrapped up nicely in a single session.
Using Session.Load in this manner avoids hitting the database as described here
If you don't do this, what you're essentially saying to NHibernate is that you have a company object which you have assigned an ID and now want to save it with all the properties set to Null or empty string values or whatever and that is not what you want.
Alternatively you could create a Save specific Domain Object that looks like this:
public abstract class Entity<IdK>
{
public virtual IdK Code { get; protected set; }
}
public class SavableContact : Entity
{
public virtual string Name { get; set; }
public virtual IdK CompanyId { get; set; }
}
Which maps directly to the Contact table in your database so that when you Save this entity you can literally just map back the CompanyId from your view model and NHibernate will only save that value back and not care at all about the company objects.
It's a case of working out what works best for you. I personally prefer the first option as the extra bit of logic helps simplify the domain model, however if you're creating and exposing a public API then the second method might make more sense.

Resources