Hello I'm trying to do the impossible apparently.
I need a self referenced table with a many to many relationship to itself that also has a specific order in c# entity framework (4.2) database first.
Think of it like Friends having Friends in which they order their friendship > Best Friend to Worst Friend.
Is there anyway to do this without using the "FriendToFriend" relationship entity? I would like to be able to use Friend.Friends (removing the order column creates it), but I would have a default order based on their friendshipOrder. My work around is looking like extending the generated classes to have a new property for Friends in order.
Any one else have any better ideas?
Entity framework does not support ordered collections. This is one of many situations where EF shows its immaturity.
Try nHibernate if it is a viable option. It supports ordered collections.
With EF you will have to map the intermediate table with extra column and manually adjust the ordering according to your logic.
I know I'm late to this, but when designing this as a data model, I would prefer to add a relationship table, and that relationship table should have a property that defines the order (for example, worst friend is 0, best is 100).
Then, in EF, I would explicitly order by that property, if the list I'm retrieving should be of that order.
That means that whatever method you use to query the data, that relationship can be consistently used. So if you were using EF, you could use it (although, yes, it's not as handy as Friend.Friends, but the code would be clearer as to its intention - Friend.FriendRelationships.Select(p => p.Friend).OrderBy(p => p.OrderValue)), and if you were using direct SQL, then you could use it too.
If I came across Friend.Friends in code, I would have no idea what ordering would be applied to it.
If you must have it though, you could always add it as a non-db property -
public class Friend
{
public virtual List<FriendRelationship> UnorderedFriendList { get; set; }
[NotMapped]
public IEnumerable<Friend> Friends
{
get
{
return UnorderedFriendList.Select(p => p.Friend).OrderByDescending(p => p.OrderValue);
}
}
}
Related
I'm following this tutorial in order to implement a local database (using SQLite) for my WPF application.
Everything works as it should, although I have a logical problem I don't know how to solve using this approach. I'll simplify it below.
Database-wise, I have 2 tables (A,B) which share a many-to-many relationship, and thus require a JOIN table as well (ABJoin).
In my actual code however, I'd like to use only 2 models: A and B, which each having a list of the other type. Like this:
public class A {
// ...fields
List<B> bList;
}
public class B {
// ...fields
List<A> aList;
}
How can it be implemented in EF+SQLite?
Searching online, I have found some solutions, but nothing that applies to SQLite, so I was not sure how they'd work.
Configure Many-to-Many Relationships in Code-First
If you are using many to many join table then your each class should have a list of the join table.
It cannot work the way you are thinking.
Are you sure that it is a good idea not to have a third entity?
Lets say your two entities were DepartmentStore and Product, a typical example for an n:n relationship. A department store can sell many products and a product may be available in many departments stores. This results in a third entity which connects the two above, in the example above this would something like ProductAvailability.
If you think about it more careful, then you might realize that the new connecting entity might have properties of its own. In my example this might be NumberOfProducts, will states the available quantity of a product in a certain department store.
In my experience, it is quite common for the connecting entity to have a real value that goes beyond just connecting two other entities.
I also took a look at you example which it about Album and Artist entities.
Do you want to make a data model where an Album can be created by more than one Artist?
Entity Framework doesn't have automatic many-to-many mapping.
Instead of this, you can map A and B to intermediate table as one-to-many.
If you are not obliged to use only EF, I suggest to try NHibernate ORM instead.
It has convenient many-to-many mapping and generally more powerful.
I have linked 2 Entities Project, Train with a many to many relationship.
Now, I want to add an existing Train to Project.Trains. Unfortunately, the collection has a lot of entries. When I write project.Trains.Add(...) it materializes the complete collection and this takes a lot of time. Is there a way to tell EF that I want to add the Train to the Project without materializing the collection, so that the action is faster?
Assuming that the Train.Projects collection will have fewer items than its Project.Trains counterpart, a quick solution would be adding the Project to the Train instead of the other way around:
train.Projects.Add(project);
Yes, there is a way of doing it, but it is very difficult, and it involves digging into the very interna of EF. If you use the proxies generated by EF, they will typically implement IEntityWithRelationships. You will be able to access the relationship manager as
var entityWithRelationships = project as IEntityWithRelationships;
var relatedEnd = entityWithRelationships.RelationshipManager.GetRelatedEnd("RelationshipName as found in Metadata");
With this setup you should be able to add the Train as follows:
context.Trains.Add(train);
relatedEnd.Add(train);
As said, it is a long way to make it work, but it would solve your problem.
You can:
1- Turn off lazy loading. This way, accessing Trains doesn't make a
query to DB. But be aware of the side effects because you may have
already relied on it.
2- Close to Relational Database world: Add FK property to Train entity and set it on the newly created
object:
newTrain.ProjectId = project.Id
3- Even more Close to Relational Database world: Add junction table of ProjectTrain, to implement Many-to-Many relation
public class ProjectTrain
{
public int Id {get;set;}
public Project Project {get;set;}
public Train Train {get;set;}
}
and add this to the context:
DBSet<ProjectTrain> ProjectTrains {get;set;}
and finally, make a new entity of ProjectTrains and set the Train and Project properties
I am currently working towards implementing a charting library with a database that contains a large amount of data. For the table I am using, the raw data is spread out across 148 columns of data, with over 1000 rows. As I have only created models for tables that contain a few columns, I am unsure how to go about implementing a model for this particular table. My usual method of creating a model and using the Entity Framework to connect it to a database doesn't seem practical, as implementing 148 properties for each column does not seem like an efficient method.
My questions are:
What would be a good method to implement this table into an MVC project so that there are read actions that allow one to pull the data from the table?
How would one structure a model so that one could read 148 columns of data from it without having to declare 148 properties?
Is the Entity Framework an efficient way of achieving this goal?
Entity Framework Database First sounds like the perfect solution for your problem.
Data first models mean how they sound; the data exists before the code does. Entity Framework will create the models as partial classes for you based on the table you direct it to.
Additionally, exceptions won't be thrown if the table changes (as long as nothing is accessing a field that doesn't exist), which can be extremely beneficial in a lot of cases. Migrations are not necessary. Instead, all you have to do is right click on the generated model and click "Update Model from Database" and it works like magic. The whole process can be significantly faster than Code First.
Here is another tutorial to help you.
yes with Database First you can create the entites so fast, also remember that is a good practice return onlye the fiedls that you really need, so, your entity has 148 columns, but your app needs only 10 fields, so convert the original entity to a model or viewmodel and use it!
One excelent tool that cal help you is AutoMapper
Regards,
Wow, that's a lot of columns!
Given your circumstances a few thoughts come to mind:
1: If your problem is the leg work of creating that many properties you could look at Entity Framework Power Tools. EF Tools is able to reverse engineer a database and create the necessary models/entity relation mappings for you, saving you a lot of the grunt work.
To save you pulling all of that data out in one go you can then use projections like so:
var result = DbContext.ChartingData.Select(x => new PartialDto {
Property1 = x.Column1,
Property50 = x.Column50,
Property109 = x.Column109
});
A tool like AutoMapper will allow you to do this with ease via simply configurable mapping profiles:
var result = DbContext.ChartingData.Project().To<PartialDto>().ToList();
2: If you have concerns with the performance of manipulating such large entities through Entity Framework then you could also look at using something like Dapper (which will happily work alongside Entity Framework).
This would save you the hassle of modelling the entities for the larger tables but allow you to easily query/update specific columns:
public class ModelledDataColumns
{
public string Property1 { get; set; }
public string Property50 { get; set; }
public string Property109 { get; set; }
}
const string sqlCommand = "SELECT Property1, Property50, Property109 FROM YourTable WHERE Id = #Id";
IEnumerable<ModelledDataColumns> collection = connection.Query<ModelledDataColumns>(sqlCommand", new { Id = 5 }).ToList();
Ultimately if you're keen to go the Entity Framework route then as far as I'm aware there's no way to pull that data from the database without having to create all of the properties one way or another.
We've been using the Entity framework-code first approach and Fluent Api, and have this requirement, an entity with multiple navigation properties and the possibility of numerous entries.
This entity reflects the data of a process and a field captures whether the entity is active in the process. I've provided an example for this.
public class ProcessEntity
{
//Other properties and Navigation properties
public bool IsInProcess { get; set; }
}
What I've been trying to do is, have an another table could be a mapping table or something that will contain only the ProcessEntity items whose IsInProcess property is set to true, ie.,this table provides the ProcessEntities that are active in the process.
The whole idea and thought behind this segregation is that, a lot of queries and reports are generated only on the items that are still in process and querying the whole table every time with a Where clause would be a performance bottleneck. Please correct me If I'm wrong.
I thought of having a mapping table but the entries have to be manually added and removed based on the condition.
Is there any other solution or alternative design ideas for this requirement?
Consider using an index.
Your second table is what an index would do.
Let the DB do its job.
Given that a boolean isnt a great differentiator, a date or similiar as part of the index may also be useful.
eg How to create index in Entity Framework 6.2 with code first
We are working with a rather large model in a EF 6.1 code first setup and we are using ints for entity ids.
Unfortunately, this is not as typesafe as we would like, since one can easily mix up ids, for example comparing ids of entities of different types (myblog.Id == somePost.Id) or similar. Or even worse: myBlog.Id++.
Therefore, I came up with the idea of using typed ids, so you cannot mix up ids.
So we need a BlogId type for our blog entity. Now, the obvious choice would be to use an int wrapped in a struct, but you cannot use structs as keys. And you cannot extend int... - wait, you can! Using enum!
So I came up with this:
public enum BlogId : int { }
public class Blog
{
public Blog() { Posts = new List<Post>(); }
public BlogId BlogId { get; set; }
public string Name { get; set; }
public virtual List<Post> Posts { get; set; }
}
internal class BlogConfiguration : EntityTypeConfiguration<Blog>
{
internal BlogConfiguration()
{
HasKey(b => b.BlogId);
Property(b=>b.BlogId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
So now we have typesafe ids - comparing a BlogId and a PostId is a compile time error.
And we cannot add 3 to a BlogId.
The empty enums may look a bit strange, but that is more of an implementation detail.
And we have to set the DatabaseGeneratedOption.Identity option explicitly in our mapping, but that's a one-time effort.
Before we start converting all our code to this pattern, are there any obvious problems?
Edit:
I probably need to clarify why we must work with ids instead of full entities in the first place. Sometimes we need to match entities in EF Linq queries - and comparing entities doesn't work there. For example (building on the blog example and assuming a somewhat richer domain model): Find comments on the current users blog entries. Remember, that we want to do it in the database (we have lots of data) and we assume there are no direct navigational properties. And the currentUser is not attached. A naive approach would be
from c in ctx.Comments where c.ParentPost.Blog.Author == currentUser
This doesn't work, since you cannot compare entities in EF Linq.
So we try
from c in ctx.Comments where c.ParentPost.Blog.Id == currentUser.Id
This compiles and runs but is wrong - it should have been
from c in ctx.Comments where c.ParentPost.Blog.Author.Id == currentUser.Id
Typesafe ids would have caught it. And we have much more complex queries than this. Try "find comments to current users blog entries made by specific other user which the current user has not himself commented on later".
Regards, Niels
It's an interesting approach, but the question is: is it worth it and what are the consequences?
You could still do something like
if ((int)blog.BlogId == (int)comment.CommentId) { }
Personally I would invest more time in educating people, writing good tests, and code reviews, instead of trying to add some form of extra complexity that influences the way you use and query your entities.
Think - for example:
What effect does this casting have on performance in LINQ queries?
How would you enforce this if you expose your operations through Web API of WCF?
Does this work with navigation properties??
Also, you are limited in the types you could use as primary key; I don't believe this works with Guids.
A way of additional protection is to have your domain layer handle these kinds of things by accepting entity instances instead of ID's.
I was not even familiar with this usage, but did a little digging and even the EF team says it's do-able. From their initial blog post on enum support in EF, this is listed:
Enums as keys
In addition, properties of enum types can participate in the definition of primary keys, unique constraints and foreign keys, as well as take part in concurrency control checks, and have declared default values.
source: http://blogs.msdn.com/b/efdesign/archive/2011/06/29/enumeration-support-in-entity-framework.aspx
I have not ever done this myself, but that quote gives me confidence. So it's possible, but as L-Three suggests: really consider if it's what you want (pros & cons .. but sounds like you have already done that) and test test test!
I know I'm a bit late to this party, but I've used this technique and it definitely works!
Type safety works exactly as you suggest. Compiler will catch mistakes such as
from c in ctx.Comments where c.ParentPost.Blog.Id == currentUser.Id
And it prevents silly maths.
currentUser.Id++;
currentUser.Id * 3;
Navigation properties still work fine too, as long as both ends of the navigation are the same enum type.
And the SQL queries work just as they do with an int.
It's certainly an interesting idea!
Can you use typesafe entity IDs? - Yes!
Should you? I'm not sure. It doesn't seem that this is how EF was designed and feels a little hacky.
I really don't try to bash you, but how can one mix up Ids of Type X with Ids of Type Z?
I never met anybody who did stuff like myBlog.Id++ either (or at least not without getting fired).
Anyhow, here is a solution which seams to be less work and better maintainable (especiall for the db-admins):
-In the TypeConfiguration, create an Id through the fluent API (you'll see why later)
-Create an abstract base-class for all your entities with:
*property: proteced int Id
*method: public int getIdValue()
*method: public bool isSameRecord(T otherEntity) where T: EntityBaseClass
I guess the first method are self-explanatory, the isSameRecord will take the other instance of your base-class, does a type-check first and if it passes it, it will do a id-checkup, too.
This is an untested approach, there's a good chance you can't create protected identifiers.
If it doesn't work, you could create public int _id and just tell your team to not use it directly.
Not sure that this will work in EF but one thing you could do is to have your entities implement IEquatable<T>:
For example your Blog class:
public class Blog : IEquatable<Blog>
{
// other stuff
public bool Equals(Blog other)
{
return this.Id.Equals(other.Id);
}
}
Alternatively you could use a more flexible ORM such as NHibernate. If this is of interest, let me know and I'll expand my answer.