I'd like this class:
public class InvertedList<T> : List<T>{
public bool IsInverted { get; set; }
}
when used in the entity like this:
public class Parent {
public InvertedList<Child> Children { get; set; }
}
to map into database tables like
CREATE TABLE Parent (
Child_IsInverted bit
);
CREATE TABLE Child (
ParentId int
)
I've tried putting [Column] on the IsInverted property, [ComplexType] on InvertedList class, but the property is always ignored.
Is there any way to do something like this or anything similar?
Of course I can do it manually like
public class Parent {
public bool Child_IsInverted { get; set; }
public List<Child> Children { get; set; }
}
But I really don't like to put all those Child_IsInverted properties (I'll have quite a lot of such invertable lists) on Parent entity. The only way I can think of to at least partially implement this would be to have separate domain and db models, and transform it using the repository - this way I could work using desirable model, but it looks like a little bit too much effort for such a task. Can you offer any other options?
When EF deserialize a List<> (everything implementing ICollection<>) it does not serialize other properties than the content.
Just a suggestion, Compex types that could be an option does not support generics and does not support navigation properties and you here have both.
Related
Hi my Entity is ParameterDetail as follows:
public class ParameterDetail
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
[NotMapped]
public string Description { get; set; }
//..other columns removed for brevity
public int LookupValueId { get; set; }
}
I call my stored procedure and load the results as follows...
List<ParameterDetail> paramDetails = this.ParameterDetails.FromSqlRaw("EXEC dbo.GE_GetStartParameter #GuidelineName={0}", guidelineName).ToList();
Now this all is working fine but now I have to call a slightly different procedure which does not have LookupValueId..
List<ParameterDetail> paramDetails =this.ParameterDetails.FromSqlRaw("EXEC dbo.GetParameterDetails #ParameterId={0}", nextParam).ToList();
I don't want to add another EntityModel just for this one column....
Can i use Mapped property (Data Annotation) at runtime somehow? Or could there be any other solution?
Can i use Mapped property (Data Annotation) at runtime somehow? Or could there be any other solution?
Not if you want EF to perform the mapping, at least not a good one. You can't change the attributes at runtime, but if you use Fluent configuration you could have two different DbContext subtypes that configure the same entity class differently. But that's not a very elegant solution.
You can always just execute the stored procedure with ADO.NET and map the data however you want.
In Entity Framework 6, given class A and derived class B: A, I would like to load entities A into instances of B without having to code for each property.
So given:
public class A
{
public Guid AId { get; set; }
public string Value { get; set; }
}
public class B: A
{
[NotMapped]
public string OtherValue { get; set; }
}
public MyDbContext: DbContext
{
public DbSet<A> As { get; set; }
}
I would like to:
using (MyDbContext db = new MyDbContext())
{
IEnumerable<B> Bs = db.As.LoadBsSomehow()
}
I'm guessing I could add DbSet<B> Bs { get; set; } and then in OnModelCreate I could override the table name to As perhaps. I'd like to avoid that if I can.
The purpose of doing this is that we need view models that need the underlying model plus some other properties and I don't want to mess up the models with all the different view model properties. This would simplify coding and maintenance for when the main model is changed -- the inheritance would automatically handle the changes in the derived class (view models).
I can then set the additional properties of the Bs in a Select or other method.
Also, I do NOT want to use reflection. I can code that up if I need it. I'd rather find out if EF 6 has the ability to do this natively.
UPDATE: I can do DbContext.Database.SqlQuery<T>. I would prefer to be able to use LINQ instead of writing SQL. I have no problem writing SQL, but LINQ is much more maintainable from a code perspective. Perhaps if I can use LINQ to create an IQueryable<B> and get the SQL for it?
I have found a solution that works (using DTOs and AutoMapper), which is reproduced below, but I would prefer an answer that lists the different approaches to the problem with examples and this will be marked as the answer if received.
In my entity model I have a navigation property that goes from a child entity to the parent entity. My project was working swimmingly. Then I began to use AutoFixture for unit testing, and testing failed, AutoFixture saying I had a circular reference.
Now, I realise that circular reference navigation properties like this are OK within Entity Framework, but I found this post (Use value of a parent property when creating a complex child in AutoFixture), where Mark Seemann, the creator of AutoFixture states:
"For the record, I haven't written an API with a circular reference for years, so it's quite possible to avoid those Parent/Child relations."
So, I want to understand HOW a domain model can be refactored to avoid child/parent relations.
Below are the entity classes in question, the repository method, and how I use the property causing the circular reference in my View. The perfect answer would explain the different options I could choose from with examples, and the basic pros/cons of each approach.
Note: The property causing the circular reference is User, in the UserTeam model.
Models:
public class UserProfile
{
public UserProfile()
{
UserTeams = new HashSet<UserTeam>();
Games = new HashSet<Game>();
}
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public virtual ICollection<UserTeam> UserTeams { get; set; }
public virtual ICollection<Game> Games { get; set; }
}
public class Game
{
public Game()
{
UserTeams = new HashSet<UserTeam>();
}
public int Id { get; set; }
public int CreatorId { get; set; }
public virtual ICollection<UserTeam> UserTeams { get; set; }
}
public class UserTeam
{
public UserTeam()
{
UserTeam_Players = new HashSet<UserTeam_Player>();
}
public int Id { get; set; }
public int UserId { get; set; }
public int GameId { get; set; }
public virtual UserProfile User { get; set; }
public virtual ICollection<UserTeam_Player> UserTeam_Players { get; set; }
}
Repository Method
public IEnumerable<Game> GetAllGames()
{
using (DataContext)
{
var _games = DataContext.Games
.Include(x => x.UserTeams)
.Include(x => x.UserTeams.Select(y => y.User))
.ToList();
if (_games == null)
{
// log error
return null;
}
return _games;
}
}
View
#model IEnumerable<Game>
#foreach (var item in Model){
foreach (var userteam in item.UserTeams){
<p>#userteam.User.UserName</p>
}
}
Now, if I remove the 'User' navigation property, I wouldn't be able to do '#userteam.User.UserName'
So, how do I refactor the domain model to remove the circular reference, whilst being able to easily loop through Games, and do something like
UserTeam.User.Username?
I had a similar problem with AutoFixture and EntityFramework a while ago. My solution was to add an extension to AutoFixture, that allows you to build a SUT with a few recursions. That extension has recently been adopted in AutoFixture.
But I understand that your question was not about how to make AutoFixture construct recursive data structures, which is indeed possible, but how to create domain models without recursion.
First, you have tree or graph structures. Here anything but recursion would mean indirection through loose coupled node ids. Instead of defining an association, you would have to traverse the tree query-by-query or cache the whole thing and traverse by node-key lookup, which may be impractical depending on the tree-size. Here it is very convenient to make EF do the work for you.
The other common structure is a two-way navigational structure similar to your user / game scenario. Here it is often not that inconvenient to prune the navigation flow to a single direction. If you omit one direction, say from game to team, you can still easily query all teams for a given game. So: User has a list of games and a list of teams. Team has a list of games. Games have no navigational reference to either. To get all users for a specific game you could write something like:
var users = (from user in DataContext.Users
from game in user.Games
where game.Name == 'Chess'
select user).Distinct()
I have found a solution that works (using DTOs and AutoMapper), which is reproduced below, but I would still prefer an answer that lists the different approaches to the problem with examples, in particular whether this is a desirable solution, or whether I should stick with the navigation properties as they were, get rid of AutoFixture, and when it comes to serializing for json just utilise other work arounds (attributes etc)...
So, in my View Model, I added a couple of classes:
public class GameDTO
{
public int Id { get; set; }
public int CreatorId { get; set; }
public ICollection<UserTeamDTO> UserTeamsDTO { get; set; }
}
public class UserTeamDTO : UserTeam
{
public UserProfile User { get; set; }
}
And in my controller, I use AutoMapper to map the Game / UserTeam objects from the repository to my DTO objects, and return the IList _gamesDto to the View.
var _games = _gameRepository.GetAllGames();
IList<GameDTO> _gamesDto = new List<GameDTO>();
IList<UserTeamDTO> _userteamsDto = new List<UserTeamDTO>();
GameDTO _gameDto = new GameDTO();
UserTeamDTO _userteamDto = new UserTeamDTO();
Mapper.CreateMap<Game, GameDTO>();
Mapper.CreateMap<UserTeam, UserTeamDTO>();
foreach (Game _game in _games)
{
foreach (UserTeam _userteam in _game.UserTeams)
{
_userteamDto = Mapper.Map<UserTeamDTO>(_userteam);
_userteamDto.User = _userRepository.GetUser(_userteam.UserId);
_userteamsDto.Add(_userteamDto);
}
_gameDto = Mapper.Map<GameDTO>(_game);
_gameDto.UserTeamsDTO = _userteamsDto;
_gamesDto.Add(_gameDto);
}
I had a similar problem recently which also impacted serializing JSON objects. I decided to remove the circular references from my data model.
I first removed the redundant navigation properties which were creating the circular references. I made sure that my resulting tree of data made sense. This allowed me to make it clear which objects own which relationships.
This also made EF unable to automatically reason about my relationships. I had to specify the One-to-Many and Many-to-Many relationships using the FluentAPI. I found a solution here: https://stackoverflow.com/a/16719203/1887885
Hope this is helpful.
I haven't been able to find someone else with this issue specifically so here goes.
I have a simple model where one entity simply references another as a parent-child or one-to-many relationship defined like this:
public class Parent
{
public int ID { get; private set; }
public string Name { get; private set; }
}
public class Child
{
public int ID { get; private set; }
public string Name { get; private set; }
public virtual Parent Parent { get; private set; }
}
I am creating speicific mapping files for each, which work great for all the normal properties except for the related entity. It is always coming up null. No matter whether i have the virtual/private accessors on the property it will not load UNLESS i pull a copy of the parent separately from the context first. My mapping looks like this:
HasRequired(t => t.Parent).WithMany().Map(t => t.MapKey("ParentID")).WillCascadeOnDelete();
Is there anything I am doing wrong with this? I cannot for the life of me figure this out. Just so I cover all the bases, I am loading the entity like this:
Context.Set<Child>().FirstOrDefault(x => x.ID == 1);
And lastly here are some constraints I have:
I cannot have the foreign keys in my model as properties.
I cannot have a collection of children from the parent.
I finally figured it out. After much trial and error I noticed that having a parameterless constructor marked as internal, EF cannot create its dynamic proxy class of your type and therefore disables all lazy loading. I have two contructors, one for EF to hydrate objects, and another with parameters requires for callers to create my entity. Once I changed the signature to protected internal it started working. So I changed this:
internal Child() {}
to
protected internal Child() {}
May be you hasn't enable lazy loading .Try this,
Context.Set<Child>().FirstOrDefault(x => x.ID == 1).Include(c=>c.Parent);
A little new to EF, so please bear with me if the answer to this is obvious. I'm doing a tutorial that uses EF, and two DbSets are defined like this:
public DbSet<BrokerageAccount> BrokerageAccounts { get; set; }
public DbSet<Customer> Customers { get; set; }
The customer class looks like this-- it's a POCO (some code cut for brevity):
public class Customer
{
public Customer()
{
BrokerageAccounts = new HashSet<BrokerageAccount>();
}
// Primitive properties
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// Navigation properties
public ICollection<BrokerageAccount> BrokerageAccounts { get; set; }
}
}
The BrokerageAccount class is a POCO as well, very similar in design to Customer.
So far so good. The code I have a question about is below. There is an association made in the main program between Customer and BrokerageAccount that I don't follow. The code reads like this:
public Customer GetCustomer(string custId)
{
using (var context = DataContext)
{
return context.Customers
.Include("BrokerageAccounts").SingleOrDefault(c => c.CustomerCode == custId);
}
}
I can't figure out how the association/join is made between Customer and BrokerageAccount. I don't see any config or other files in my VS 2010 project that tells what associates the two DbSets, what foreign key column to use, etc.
Perhaps I'm missing something obvious or a mapping file of some sort, but just because Customer has an ICollection of BrokerageAccount along with a comment above that says "Navigation Properties", doesn't make it so. In EF, how are those associations established?
The normal way of setting up the navigation properties is to use the ModelBuilder, This gives you a fluent api to set up the associations, take a look at this for some in depth stuff about how you go about this.
http://xhalent.wordpress.com/2011/01/21/configuring-entity-framework-4-codefirst/
Entity framework will guess at what you meant if you dont set up the nav properties manually, in the above case it will probably set up your nav properties as expected as you only have a single 1-* relationship between customer and BrokerageAccount which appears to be named sensibly.
There is also an attribute method that you can use to set up the navigation properties.