I am new in MVC, so I have problem to understand what is purpose of HashSet in model.
I am using ADO.net Entity Data model, system auto generate model like ..
public partial class Country
{
public Country()
{
this.States = new HashSet<State>();
}
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<State> States { get; set; }
}
any one can explain in simple language why I should use a HashSet here?
HashSet is an optimized set collection. It helps eliminates duplicate strings or elements in an array. It provides a simple syntax for taking the union of elements in a set. This is performed in its constructor.
Represents a set of values.
To browse the .NET Framework source code for this type, see the Reference Source.
StackOverFlow Reference
HashSet basically is a collection of distinct values removes the duplicates and is written within the constructor. So when the default strings are initialized to a field, it performs a check to the database whether duplicate values exists. If yes, HashSet removes them. Here is the good example of HashSet.
Suppose your table name is Student
public class Example
{
public Example()
{
this.Student= new HashSet<Student>();
}
public int DivisionID { get; set; }
public string DivisionName { get; set; }
}
It removes the duplicate strings within the table 'Student' with no specific order stored in it. Important note here is that it doesn't remove the duplicate from the table records, but it removes the duplicates from the table fields if any.
If you want more then you can visit this link and get your answers here: Understanding HashSet
Hope this helps.
Related
I am stuck.
I have two entities in EF6 CodeFirst, let's say:
class Child
{
public virtual Parent AssignedParent { get; set; }
}
class Container
{
public virtual ICollection<Child> Children { get; set; }
public Child ActiveChild { get; set; }
[NotMapped]
public bool hasActiveChiled { get { return ?????; } }
}
The later is mapped like this:
this.HasOptional(t => t.ActiveChild)
.WithOptionalDependent(t => t.AssignedParent)
.WillCascadeOnDelete(false);
The logic: a parent has many children, but at most one is the active one.
The tables and relationships are generated as expected. It is working just great in almost all cases.
But I need to test sometimes if there is any ActiveChild set or not.
The probelm is that the poperty is null when I don't use .Include when querying indifferent if the underlying table column (auto generated as ActiveChild_id) has value or is null. I can not always ensure to have .Include for that property. You might notice, that ActiveChild is not virtual, thus should not be lazy loaded at all.
1) Is there any way to map the generated foreign key to a property? It won't work if I simply add it and I can't figure out an other configuration that yields what I expect. And .WithOptionalDependent has no .WithForeignKey
2) Is there any way to get to the underlying ActiveChild_id field value? That would help me the most.
Thank you
I have a view that has one field that is editable.
My thought was to create an update query and map it to that view, but breeze is throwing an error when I call SaveChanges.
** Error **
TypeError: Cannot read property 'map' of undefined
at i._prepareSaveResult (breeze.min.js:formatted:5066)
at Object.it.AbstractDataServiceAdapter.i.saveChanges.n.ajax.success (breeze.min.js:formatted:4755)
at n (breeze.min.js:formatted:4818)
at angular.js:9408
at processQueue (angular.js:13248)
at angular.js:13264
at Scope.$get.Scope.$eval (angular.js:14466)
at Scope.$get.Scope.$digest (angular.js:14282)
at Scope.$get.Scope.$apply (angular.js:14571)
at done (angular.js:9698)
EDIT
My view is mapped to an entity
public partial class Shop
{
public Shop()
{
this.Notes = new HashSet<SoNote>();
}
public int SoId { get; set; }
public int DetailId { get; set; }
//[other properties removed for brevity]
public string ShopTech { get; set; }
public virtual OrderEdit OrderEdit { get; set; }
public virtual ICollection<SoNote> Notes { get; set; }
}
}
SoId and DetailId are my key and I want the user to be able to update ShopTech.
This is using model first.
I'm not sure this error is the actual root cause. How is your view defined and what kind of database are you using? There are restriction on the database as far as updating a view is concerned. In most cases views are read-only and a SQL update statement against it will fail. Certain types of views are editable. For the other cases, EntityFramework 6 allows you to define insert/update/delete stored procedures. Have you defined an update stored procedure? As long as EF is able to update your entity, Breeze should be just fine with that.
Here's more info on using stored procs with code first. https://msdn.microsoft.com/en-us/data/dn468673.aspx
I wish to give a Person as defined below, the ability to print a vCard out of my system. To provide the user with privacy options, the user can select whether to show/hide certain properties. In it's simplest form, I need to have a separate table that would hold the user's choices.
I was wondering if it was possible to build this configurator table using reflection. As shown in the Person model below, I could decorate properties with a custom attribute, and then using those properties, construct and persist a model that would have a bool property for every decorated Person property.
public class Person
{
public string UserName { get; set; }
public string FirstName { get; set; }
[DisplayOnVCard]
public string LastName { get; set; }
[DisplayOnVCard]
public string Email { get; set; }
[DisplayOnVCard]
public string MobilePhone { get; set; }
}
** where [DisplayOnVCard] is a custom attribute.*
At the end of this, I expect a table in the db that would correspond to this:
public class VCardConfigurator
{
public bool LastName { get; set; }
public bool Email { get; set; }
public bool MobilePhone { get; set; }
}
This is just a sample representation of what is actually a huge entity. Which is why I hope to avoid manually mapping a bool field to each optional property.
I believe this problem domain is quite similar to how, for instance, privacy settings work on social networking sites, yes?
While I was typing this, I did ponder upon the possibility that if down the line I was to remove the attribute from one of the properties, what implications that might have. Needs some thought!
Further reading for self:
Programmatically adding properties to an MVC model at runtime
There is a huge possibility that I am galloping down a totally wrong path! If that is the case, please advice so!
#1 Update
I am not sure its possible to add or remove attributes for an instance since attributes are at the class level, but their property values can be changed (Since they are instances).
My suggested solusion
I am not sure what you mean in "I expect a table in the db that would correspond to this",
since you can't have a table in the database that contains only the columns of the non-privacy properties for each user.
You will need a dedicated table for this mapping (Lets say 'PrivacyMappings' table), with these columns:
UserId, PropertyName, IsPrivate.
When a user is added, all the properties will be added to this table with a default privacy settings (for instance, all properties are non-private by default).
You can add the properties by iterating over them and insert them as you said.
You can use the following class in entity framework:
public class PrivacyMapping
{
public int UserId {get;set;}
public string PropertyName {get;set;}
public bool IsPrivate {get;set;}
}
Adding the default privacy settings when a user being added:
// retrieve user model properties.
foreach (property in properties)
{
//iterrate over the user Properties.
context.PrivacyMapping.Add(new PrivacyMapping(user.userId, propertyName, isPrivate);
}
context.SaveChanges()
Now you can take all the user non-private properties by
context.PrivacyMapping.Where(p=>p.UserId == user.id && !IsPrivate).Select(p=>p.PropertyName);
And now you can deal with information any way you want.
For example, you can have a VCardItems class, that receive an user id/object in its c'tor and stores a dictionary of the allowed properties by their names.
public class VCardItems{
private Dictionary<string, object> properties{get;set;}
public VCardItems(User user)
{
// initiate values..
}
public object this[string name] {
get
{
if (properties.ContainsKey(name))
{
return properties[name];
}
// A private property.
return null;
}
set
{
properties[name] = value;
}
}
}
There is other options of how to use the data, for example with ActionFilter that in this case sets the private properties to null or storing the non-private data in the HttpContext.Items dictionary,
but it really up to you.
First message
Before we get into details, I wonder how you expect to use this class.
If a view (or whatever going to handle it), going to receive have a runtime-generated class for example, how you gonna handle it?
How you gonna know what properties this model has?
Assume we have POCO class for Entity Framework 4:
public class Order
{
public long Id { get; set; }
public ISet<OrderItem> OrderItems { get; set; }
}
And this method to retrieve the order from database:
public Order GetOrder(long orderId)
{
using (var context = new MyModelEntities())
{
return context.Orders.Include("OrderItems").Where(order => order.Id == orderId).FirstOrDefault();
}
}
So suppose we do this:
Order myOrder = GetOrder(1);
Is myOrder.OrderItems a HashSet or SortedSet? Is there a way to control this?
Good question.
As far as i know (and there is no MSDN/blog/article i am aware of that dispells/proves this), a navigational property can be of any type as long as it implements ICollection<T>.
Both HashSet<T> and SortedSet<T> implement ICollection<T>, so either would be viable candidates.
Did you step through the code? You should be able to see which concrete class get's resolved.
Most people use ICollection<T> / IList<T>. Why are you wanting to declare the property as ISet<T>?
Why don't you just declare which type you want, instead of the interface.
Or you could try using dependency injection (For<ISet>().Use<HashSet>()).
I'm still learning, but with the stackoverflow commnuties help, I've been able to get closer and closer.
What I have right now is a View "Index.aspx":
System.Web.Mvc.ViewPage<Data.Models.GetDealsModel>
The Model:
public class GetDealsModel
{
// set up the model
public string DealId { get; set; }
public string StreetAddress { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public string Logo { get; set; }
public string Website { get; set; }
public string TotalRows { get; set; }
}
And the controller:
public ActionResult Index()
{
LinqToDealsDataContext db = new LinqToDealsDataContext();
XElement xmlTree = XElement.Parse("<Request><ZipCode>92612</ZipCode></Request>");
var deals = db.spSearchDeals(xmlTree);
return View(deals);
}
And with this configuration I'm now getting this error:
The model item passed into the dictionary is of type 'System.Data.Linq.SqlClient.SqlProvider+SingleResult`1[Data.Models.spSearchDealsResult]', but this dictionary requires a model item of type 'Data.Models.GetDealsModel'.
I'm guessing that there's an issue connecting my Controller to my Model... I'm not sure why. PLEASE help me connect this final peice.
NOTE: I do understand that eventually I should separate my logic in the controller into a Repository Pattern, but for now, this will do.
You need to translate the data coming back from this call:
var deals = db.spSearchDeals(xmlTree);
into a GetDealsModel type. So something like:
GetDealsModel dealsModel = new GetDealsModel()
{
DealId = deals.DealId,
StreetAddress = deals.StreetAddress,
....
};
return View(dealsModel);
The reason being that your View is strongly typed to take a GetDealsModel, but your deals variable is not of that type and it gives you that exception when you pass it to the View.
You should create object of type GetDealsModel, but your DB Query returns object of type Data.Models.spSearchDealsResult. Try something like:
return new GetDealsModel
{
DealId = deals.Id,
// other fields here
}
Add to your learning curve list the following items:
Repository Pattern
Ask yourself the following question: Why do I need a service layer?
Read Steven Sanderson's book. It teaches you to think in MVC.
The above applies to your problems because your issues are clearly related to having code in your Controllers that should be in your Model (ie, data access code should be in a repository class). Ie, you are not thinking in MVC.
Your model should include the necessary repository classes, eg, DealRepository.
You need a Service class to map the objects your repository digs out of your database to your model class: that way conversion problems are encapsulated into the Service Layer code.
If you do this, you can then write in your controller:
public ActionResult Index()
{
return(DealService.GetByZipcode(92612));
}
Where DealService.GetByZipcode basically just maps DealRepository.GetByZipcode(92612) to your model class and returns the mapping result.
The DealRepository.GetByZipcode method would be roughly:
public static DealEntity GetByZipcode(string zip)
{
LinqToDealsDataContext db = new LinqToDealsDataContext();
XElement xmlTree = XElement.Parse("<Request><ZipCode>" + zip + "</ZipCode></Request>");
var deals = db.spSearchDeals(xmlTree);
return deals;
}
The DealEntity class is just whatever Linq gives you for your table.
The reason WHY for all this:
The reason for this structure is as follows:
a. All you data access code is in one place: DealRepository. You can test and debug that independently of everything else.
b. The mapping code is all in one place: DealService. You can test and debug that independently of everything else.
c. In other words, you need to properly separate your concerns.
The problem with your existing code is precisely that you have NOT separated concerns. Ie, you have taken a dash of MVC and put it in a food processor and ended up with mush full of problems that are way more difficult to deal with than they need be.
Your model is mixed into your controller, there is no repository, no service layer.
So hold your horses just a while and take the time to read Steve Sanderson's book.
I would also try modelling a simpler problem. That xml parsing makes my head hurt even on a good day.
NOTE:
You could seriously improve your naming conventions. LinqToDealsDataContext? You're kidding, right?