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
Related
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 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.
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>()).
Using Entity Framework 4 CTP5 Code First and this example
Is it possible to access the discriminator value?
I would like to use it in a projection like
context.BillingDetails.Select(x => new { Number = x.Number, DiscrimitatorValue = /* how do I get the discriminator value? */ });
From this post I understand the discriminator cannot be mapped to a property but is there any other way of accessing it?
I may be late to the game on this one, but I just added a getter property to the base class that returned the name of the current type:
public string DiscriminatorValue {
get {
return this.GetType().Name;
}
}
Since by default EF is going to use this same value for the Discriminator field, they will match up.
In EF Core 2.1 (I haven't checked previous versions) it's enough to add Discriminator to the base abstract class as private set property. It will be mapped with adequate value.
public abstract class Entity
{
public int Id { get; set; }
public string Discriminator { get; private set; }
}
EF by itself will automatically insert appropriate discriminator value to the database and will automatically set it to an object on read.
After further information from Morteza Manavi in the comments of his post the simple answer is no
you should be aware that the discriminator column is used internally by Code First and you cannnot read/write its values from an inheritance mapping standpoint.
To access the discriminator I would have to execute a SqlQuery against the database or change my mapping strategy.
Reason aside, I recently ran into the same problem but believe this is still relevant for v4 of the EF Framework.
First, create a view which selects the discriminator value into two columns.
create view dbo.vw_BillingDetail
as
select BillingDetailId, DiscriminatorValue, DiscriminatorValue as DiscriminatorValue2 from dbo.BillingDetail
go
Secondly, map the view to your entity during context creation:
modelBuilder
.Entity<BillingDetail>()
.HasKey(n => n.BillingDetailId)
.Map(map =>
{
map.ToTable("vw_Person");
})
Thirdly, define your discriminator mapping for your derived class using one of the columns in your view:
.Map<MyDerivedBillingDetail>(map =>
{
map.Requires("DiscriminatorValue2").HasValue("YourValue");
})
Finally, define a getter and a private setter for the other discriminator column in your view with the DatabaseGenerated annotation set as Computed to prevent EF from updating/inserting for this field:
class BillingDetail
{
public BillingDetailId { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DiscriminatorValue { get; private set; }
}
You can change the private setter to be protected and set this value explicitly during the construction of your derived entities so that the discriminator has a value prior to being persisted:
class MyDerivedBillingDetail : BillingDetail
{
public MyDerivedBillingDetail()
{
this.DiscriminatorValue = "MyValue";
}
}
To expand on #Michael Black's answer for Entity Framework Core 2.1 (earlier? tested in 2.1.4)
You can use any property name, database field name and data type you want.
Create a property:
[Column("foo_type_id")]
class Foo {
public FooTypesEnum TypeId {get; set;}
}
Then in your context class with the fluent API via modelBuilder:
modelBuilder.Entity<Foo>(b => {
b.HasDiscriminator(foo => foo.TypeId)
.HasValue<SubFooA>(FooTypesEnum.SubFooA)
.HasValue<SubFooB>(FooTypesEnum.SubFooB);
});
This is really useful if you need to build composable queries that e.g., group on the discriminator, etc.
Why don't you use the following query instead?
var q = con.BillingDetails.OfType<BankAccount>().ToList();
You can add a property with the name you gave to the discriminator in EF Core. Example:
In DBContext:
...HasDiscriminator<string>("Type")..
In base class do:
public string Type { get; private set; }