Entity framework with inheritance, condition, and foreign key - visual-studio-2010

I just started to play around with Linq to entities and ran into an issue I can't figure out.
I am getting this error:
Condition member 'RelatedResources.TypeID' with a condition other than 'IsNull=False' is mapped. Either remove the condition on RelatedResources.TypeID or remove it from the mapping.
The condition that exists is a TypeID field in the abstract entity RelatedResource that defines the type of RelatedResource (Book, Link, guide, etc.). TypeID is also a foreign key and is mapped in the association with the Resource Type entity. I think this is the problem but I don't know how or why I should change this.

That usually happens when you have TypeID as a condition and also use it as a property. It might be causing problems because you are using it to map the association with ResourceType AND using it as a condition for the inheritance.

Is RelatedResources.TypeID set to be not null (ie. 'Isnull=false') in the database and in the entityframework schema?
Not sure you can both have that field as a conditional and acts as a foreign key to another table.
And would you need to if you using the conditional inheritance to determine the type?

Sounds like table-per-hierarchy (TPH) inheritance error:
https://learn.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/implementing-inheritance-with-the-entity-framework-in-an-asp-net-mvc-application
Use [NotMapped] on the base class property.
Pseudo code:
public abstract class MyBaseClass
{
[NotMapped]
public MyEnum MyEnum { get; protected set; }
}
public class DerivedOne: MyBaseClass
{
public DerivedOne()
{
MyEnum = MyEnum.Value1;
}
public string MyDerivedOneString { get; set; }
}
public class DerivedTwo: MyBaseClass
{
public DerivedTwo()
{
MyEnum = MyEnum.Value2;
}
}
public class MyDbContext : DbContext
{
DbSet<MyBaseClass> MyBaseClass { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<MyBaseClass>()
.Map<DerivedOne>(x => x.Requires("MyEnum").HasValue((int)MyEnum.Value1))
.Map<DerivedTwo>(x => x.Requires("MyEnum").HasValue((int)MyEnum.Value2));
}
}

Related

Using Automapper to map object to realm object with Xamarin and c#

I am creating an Xamarin.iOS app and a Realm database.I would like to keep my POCO objects separate from my RealmObject so what I did was use a repository pattern and within the repository I tried to use AutoMapper to map the POCO to the RealmObject
e.g. (subset)
public class PlaceRepository : IPlaceRepository
{
private Realm _realm;
public PlaceRepository(RealmConfiguration config)
{
_realm = Realm.GetInstance(config);
}
public void Add(Place place)
{
using (var trans = _realm.BeginWrite())
{
var placeRealm = _realm.CreateObject<PlaceRealm>();
placeRealm = Mapper.Map<Place, PlaceRealm>(place);
trans.Commit();
}
}
So, if I debug my code everything maps OK and placeRealm is populated OK but when I commit nothing gets saved to the Realm db. The following is my RealmObject
public class PlaceRealm : RealmObject
{
[ObjectId]
public string Guid { get; set; }
public string Title { get; set; }
public string Notes { get; set; }
}
and this is my POCO Place
public class Place
{
public string Guid { get; set; }
public string Title { get; set; }
public string Notes { get; set; }
}
And AutoMapper is initialized like so:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<Place, PlaceRealm>();
cfg.CreateMap<PlaceRealm, Place>();
});
All standard stuff. Has anyone else managed to get something similar working?
Your poco 'Place' is called 'PlaceRealm'. I suspect that is a typo. (made edit)
I suspect that Automapper is instantiating a new object overwriting your original 'placeRealm' object.
Perhaps you could try
Mapper.Map(place, placeRealm);
in place of your current mapping.
which should just copy the values to your already instatiated and tracked object.
(no need to store the return value).
You might also want to make explicit which properties (3) you are mapping as currently Automapper will map all including those in the base class.
On a side note, you may run into performance issues with Automapper. I found it to be the performance bottleneck in some apps. ExpressMapper is a nice alternative.

How to change the primary key for a EntityData derived class default string Id property to an int property?

I recently started to learn about Azure Mobile Services, I followed this tutorial about it and the classes for my model are required to inherit from the EntityData class.
From the EntityData source code, an Id property is already defined to act as a primary key, but it is defined as string which doesn't work for my Model that uses int.
My class looks like this:
public partial class Role : EntityData
{
public Role()
{
this.Users = new HashSet<User>();
}
[Key]
public int RoleId { get; set; }
public string Title { get; set; }
public virtual ICollection<User> Users { get; set; }
}
If I try to use this class, I get an error message saying an Id property is already defined.
Is there a way to define a different property as a primary key? In case this change is not possible, is there a way to use this string Id property as an incremental primary key?
The best solution is to use automapper. Here's a blog post that outlines how to do it, essentially you store an int, but transform it into a string when it is sent over the wire:
http://blogs.msdn.com/b/azuremobile/archive/2014/05/22/tables-with-integer-keys-and-the-net-backend.aspx

Failing to get unobtrusive client validation

I figured out that property i want to be validated has to have [Required] attribute in C#
(am i right?)
If so -my model is linq generated class - how to add this attribute?
You can do it a couple of ways:
If it's possible, make the field non-nullable in the database. This will make the field required at the data layer.
Create a partial class that adds a property to your model class. Use this property instead of the database-generated property.
For example:
public partial class YourEntity
{
[Required]
public string YourNewProperty
{
get { return this.TheRealProperty; }
set { this.TheRealProperty = value; }
}
}
Hopefully this helps
well, you could always make a new class, as a part of a Data access layer, with the same attributes, just put [required] where you want.
I believe your LINQ classes are partials. With MVC, you can use the "MetatDataTypeAttribute"
Like so
[MetadataType(typeof(UserMetadataSource))]
public partial class User {
}
class UserMetadataSource {
[HiddenInput(DisplayValue = false)]
public int UserId { get; set; }
}

NHibernate 3 Linq and IUserType

I have a table:
Page (
Id int,
Name nvarchar(50),
TemplateName varchar(50)
...
)
and it's mapped to domain model:
public class Page {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Template Template { get; set; }
}
Note that in the domain model, "Template" property is not of type "string".
The Template class is like this:
public class Template {
public string Name { get; set; }
// other properties...
}
"Templates" are loaded from file system. I have a TemplateManager class:
public class TemplateManager {
public static Template LoadTemplate(string templateName) {
// check if there's a folder named <templateName>
}
}
I can use IUserType to map the "Template" property.
public class PageMap : ClassMapping<Page> {
public PageMap() {
...
Property(c => c.Template, m => {
m.Column("TemplateName");
m.Type<TemplateUserType>();
}
}
}
public class TemplateUserType : IUserType {
public object NullSafeGet(System.Data.IDataReader rs, string[] names, object owner)
{
var templateName = rs[names[0]].AsString();
if (!String.IsNullOrEmpty(templateName))
{
return TemplateManager.LoadTemplate(templateName);
}
return null;
}
}
Okay, so far so good. But the problem is, how can I use Template property in Linq queries?
For exmaple:
var pages = session.Query<Page>().Where(it => it.Template.Name == "MyTemplate");
I think the solution might be to write a class (say TemplatePropertyHqlGenerator) implementing IHqlGeneratorForProperty. This is the linq query extension point provided by NHibernate 3. But how to write this TemplatePropertyHqlGenerator class?
Thanks in advanced!
The IUserType interface lets you define a type which is considered atomic. That is to say, you can then perform direct comparisons between instances of the type and NHibernate will know how to translate them.
E.g. the following query would evaluate:
var template = new Template();
session.Query<Page>().Where(it => it.Template == template);
If you want to define a type which has component values which you can then manipulate, you need to implement the ICompositeUserType interface. This interface requires you define the properties of the type as atomic elements, giving NHibernate the information it needs to understand the specific properties of the type.
As a result, it's a little more complex than IUserType to implement, but it should facilitate what you want to achieve.
Here's an understandable example of implementing the interface for a Money type: http://geekswithblogs.net/opiesblog/archive/2006/08/05/87218.aspx

Serializing EF4.1 Entities using JSON.Net

I am building an application using MVC3, Razor view engine, Repository Pattern with Unit of Work and using EF4.1 Code First to define my data model.
Here is a bit of background (gloss over it if you want).
The application itself is just an Intranet 'Menu'.
The 2 main entities are MenuItem and Department of which:
MenuItem can have many Departments
Departments can have many MenuItems
MenuItem may have a MenuItem as a parent
This is how I have defined my Entities
public class MenuItem
{
public int MenuItemId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public virtual ICollection<Department> Departments { get; set; }
public int? ParentId { get; set; }
public virtual MenuItem ParentMenuItem { get; set; }
}
public class Department
{
public int DepartmentId { get; set; }
public string Name { get; set; }
public virtual ICollection<MenuItem> MenuItems { get; set; }
}
I am using the FluentAPI to define the Self Reference Many-to-Many for the MenuItem.
The issue I am having is passing a MenuItem to the view via JSON.
The central issues are that I have a circular reference between my entities that the built in JSON parser can't deal with and I have lazy loading and proxy generation still enabled.
I am using JSON.net library from Nuget as my JSON Serializer as this seems to be a nice way round the circular reference issue. I now am unsure how to 'fix' the proxy generation issue. Currently the serializer throws The RelationshipManager object could not be serialized. This type of object cannot be serialized when the RelationshipManager belongs to an entity object that does not implement IEntityWithRelationships.
Can anyone help me with this? If I turn off proxy generation, I am going to have a hell of a time loading all of the MenuItem children so I am keen leave this on. I have read a fair amount and there seems to be a variety of different answers including projecting the entities into another object and serialize that, etc, etc. Ideally there would be some way of configuring JSON.net to ignore the RelationshipManager object?
Update
Here is what I have used as a Custom ContractResolver for JSON.Net serializer. This seems to have sorted out my issue.
public class ContractResolver : DefaultContractResolver
{
private static readonly IEnumerable<Type> Types = GetEntityTypes();
private static IEnumerable<Type> GetEntityTypes()
{
var assembly = Assembly.GetAssembly(typeof (IEntity));
var types = assembly.GetTypes().Where(t => String.Equals(t.Namespace, "Namespace", StringComparison.Ordinal));
return types;
}
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
if (!AllowType(objectType))
return new List<MemberInfo>();
var members = base.GetSerializableMembers(objectType);
members.RemoveAll(memberInfo => (IsMemberEntityWrapper(memberInfo)));
return members;
}
private static bool AllowType(Type objectType)
{
return Types.Contains(objectType) || Types.Contains(objectType.BaseType);
}
private static bool IsMemberEntityWrapper(MemberInfo memberInfo)
{
return memberInfo.Name == "_entityWrapper";
}
}
IEntity is an interface all my Code First entity objects implement.
I realise this question has an accepted answer, but I thought I would post my EF Code First solution for future viewers. I was able to get around the error message with the contract resolver below:
class ContractResolver : DefaultContractResolver
{
protected override List<System.Reflection.MemberInfo> GetSerializableMembers(Type objectType)
{
if (objectType.Namespace.StartsWith("System.Data.Entity.Dynamic"))
{
return base.GetSerializableMembers(objectType.BaseType);
}
return base.GetSerializableMembers(objectType);
}
}
This works because EF Code First classes inherit from the POCO class that you actually want serialized, so if we can identify when we are looking at an EF generated class (by checking the namespace) we are able to just serialize using the properties from the base class, and therefore only serialize the POCO properties that we were really after in the first place.
Well, you used powerful serialization API which serializes references and all members as well and now you complains that it serializes all members :)
I didn't test it but I believe this will bring you close to the solution.
JSON.NET is quite powerful tool and it should offer you the extensibility point to avoid this behavior but you will have to code it yourselves. You will need custom DataContractResolver where you define which members should be serialized. Here is the similar example for NHibernate.
You can implement some logic which will take only members present in the parent class of dynamic proxy. I hope this will not break lazy loading. To validate that current entity is proxy you can use this code to get all known proxy types:
IEnumerable<Type> types = ((IObjectContextAdapter)dbContext).ObjectContext.GetKnownProxyTypes();

Resources