If you have database tables with relationships as follows:
Person
PersonId (PK), Name
PersonDoesService
PersonId (FK), ServiceId (FK)
Service
ServiceId (PK), Type
Is it possible with Entity Framework in one statement to get all Persons that does one service based on serviceId?
The code below will do what you are asking. Make sure that your ServiceId exists.
var people = context.Service.First(s => s.ServiceId == theServiceIdIWant).Person // IEnumerable<Person>
Related
I have a model in EF similar to this
Person
PK Guid Id
PK DateTime DateSynced
Test
PK Guid Id
FK Guid PersonId
In Entity Framework 6.2, I really only care about Navigation Property on Person with reference to a collection of Tests. I do not need a property of Test.Persons or anything like that.
I really just want to have Person.Tests where Test.PersonId = Id regardless of DateSynced. There will eventually be many persons with the same Id, each with a different DateSynced DateTime.
Is this doable or do I need a Many-To-Many with an intermediate table?
I understand that EFCore has a concept of Alternate Keys and I thought I might could leverage that in this effort, but there does not seem to be a corresponding functionality in EF 6.2
Edit
I have the following Fluent rule in my OnModelCreating override.
modelBuilder.Entity<Test>()
.HasRequired(t => t.Person)
.WithMany(p => p.Tests)
.HasForeignKey(t => t.PersonId);
I get the following exception complaining about the Dependent and Principal role constraints:
The number of properties in the Dependent and Principal Roles in a relationship constraint must be identical.
As I understand it, this is because I am referencing an entity with a 2-part composite key by only one part of that key. What I am looking for is a way to do exactly that.
The foreign key on the second table must match the PK on the first.
For example, using Int for the key type for simplicity.
If I have a Person with a PK of ID: 1, SyncDate: 2019-05-22
Then I add a second variant: PK of ID: 1, SyncDate: 2019-05-23
If I go to add a "Test" record, which Person record would it reference with a FK Person ID of 1? It would reference both records, hence EF cannot support a reference of "HasRequired" pointing to a single Person record.
To reference one variant of Person ID 1, your Test record will need both a PersonId and a SyncDate to identify the record:
public class Test
{
public Guid Id { get; set; }
public Guid PersonId { get; set; }
public DateTime SyncDate { get; set; }
public virtual Person Person { get; set; }
}
modelBuilder.Entity<Test>()
.HasRequired(t => t.Person)
.WithMany(p => p.Tests)
.HasForeignKey(t => new { t.PersonId, t.SyncDate });
Tables in the database cannot reference each other based on a partial FK unless a many to 1. I.e.
Person
------
PK: PersonID
PersonComment
-----------
PK: PersonId
PK: CommentDate
In this example a Person can have many PersonComments based on the PersonID link, while a Comment can resolve back to the Person via the Person ID. As a FK.
In a table structure that has:
Person
------
PK: PersonID
PK: Version
PersonComment
-------------
PK: PersonCommentID
PersonId
PersonId in the PersonComment cannot be a FK to Person because it doesn't reflect the PK to the Person table. You can legally have this table structure, but PersonId is just a dumb, unconstrained column. You can query all Person records manually using it, but you will get all Versions of the person. There are no constraints etc. to ensure that the Person ID on a comment matches an Id on the Person table.
If you don't care about the versions of a Person You can have a Test entity with a Person ID, but EF can't associate that to Person entities, you'll have to load Person records manually from the Context.
When it comes to the purpose behind your schema structure, I would suggest looking at possible alternatives. For instance, if your goal is to track versioned data I would suggest looking at something like:
Person
PK: PersonId
** Person Fields
PersonHistory
PK: PersonHistoryId
FK: PersonId
VersionDate
** Person Fields
Test
PK: TestId
FK: PersonId (if applies to current person, or PersonHistoryId if a specific version)
Then "Person" reflects the person in it's current state, containing a collection reflecting the History. From there you can prevent modifying the Person fields via private setters and DDD-style methods which would be responsible for composing a new History record based on the current Person data before updating the Person values. This way a Person record can be historical and preserve it's ID for related entities.
can you explain what is default behaviour of #JoinColumn annotation when it's applaied to a field without any other relation annotation.
#Entity
class Employee{
#Id int id;
#JoinColumn(name = "man_id")
Employee manager;
}
how does jpa proceed it? if i.e. employee is many side of onetomany biderectional relation with department, where fetchtype lazy specified on both sides, when I access(ask collection for size) getEmployees property of department entity, eclipcelink generates sql and selects all records from employee entity also.
SELECT ID FROM deps WHERE (ID = ?)
SELECT ID, name, man_id, dep_id FROM emps WHERE (dep_id = ?)
additional requests
SELECT ID, name, man_id, dep_id FROM emps WHERE (ID = ?)
SELECT ID, name, man_id, dep_id FROM emps WHERE (ID = ?)
SELECT ID, name, man_id, dep_id FROM emps WHERE (ID = ?)
.................
If I mark this property with #OnetoOne(which is actually i mean) relation and set fetchtype lazy, everything "works correct" meaning manager property is not fetched until I ask employee for it.
SELECT ID FROM deps WHERE (ID = ?)
SELECT ID, name, man_id, dep_id FROM deps WHERE (dep_id = ?)
By not putting a relationship type/annotation, actually means JPA would not treat your attribute as an entity.
Perhaps, you already had your schema in place that's why your queries are working. However, I experimented on this and started with a fresh database. The behavior is different from what you expected. With Hibernate, my chosen JPA provider (with hbm2ddl property set to create), it generated the ff. schema:
create table Employee (
id bigint not null auto_increment,
manager tinyblob,
name varchar(255),
primary key (id)
)
Since my manager is an Employee class implementing Serializable interface, it was by default mapped to a BLOB type column.
Also by not mapping it with any relationship annotations, means that there will be no foreign key constraints applied to your manager column.
I have the following Schema:
User Table: (Primary Key)
UserId
CustomerId
Role Table: (Primary Key)
UserId
CustomerId
UserRole Table:
UserRoleId (UNIQUEIDENTIFIER (newsequentialid)) Primary Key
UserId
Customerid
RoleId
Those tables participate in many to many relationship (UserRole). I am using Entity Framework code first with mapping classes to define the database tables. So, In my mapping class for User Table, I have the following:
this.HasMany(u => u.Roles)
.WithMany()
.Map(m =>
{
m.MapLeftKey(new string[] { "CustomerID", "UserID" });
m.MapRightKey(new string[] {"CustomerID", "RoleID"});
m.ToTable("UserRoles");
}
);
Entity framework is failing with this message:
"One or more validation errors were detected during model generation:
CustomerID: Name: Each property name in a type must be unique. Property name 'CustomerID' is already defined.
UserRole: EntityType: EntitySet 'UserRole' is based on type 'UserRole' that has no keys defined.
is it possible to tell Code First that the Primary Key for my "UserRole" is UserRoleId?
The issue is when Entity Framework tries to create the UserRole Table, it would use all columns of MapLeftKey and MapRightKey to Create UserRole with PrimaryKey that has all those columns.
Any suggestions?
You need to model your classes similar to your DB, why don't you simply add the association tables? I mocked up your DB and there is no problem as long as you model all the tables.
Test it for yourself, create an EF project .edmx using code first from existing DB, I think the answer will be obvious.
i am new to Entity Data framework
i have tables
Actions ( Actionid (pk) ,Actionname , ... )
Roles ( Roleid(pk) , Rolename , .... )
ActionRoles( Actionid(pk,fk) , Roleid(fk) ) [Mapping Table]
Please Suggest me the LINQ to get the RoleNames for Perticular ActionID
(Note : there is No class created with Name ActionRoles in entitydesigner.cs as because it doesn't have any other column name then ActionId and RoleID )
Thank you in Advance
When you have a link table like this, adding all tables to the Entity Model should create 2 way relationship Properties between the 2 end tables, hiding the link table completely allowing you to access via something like:
IEnumerable<string> roleNames = Entities.Actions
.First(a => a.Actionid == actionid)
.Roles
.Select(r => r.Rolename);
where actionid is an int variable containing the actionid you're interested in.
For a discussion of how to handle many-to-many relationships such as this (both foreign keys must be in the ActionRoles primary key as indicated in the comment to your question), see these tutorials:
For EF 4.0: http://www.asp.net/entity-framework/tutorials/the-entity-framework-and-aspnet-–-getting-started-part-5
For Ef 4.1: http://www.asp.net/entity-framework/tutorials/updating-related-data-with-the-entity-framework-in-an-asp-net-mvc-application
Let's say I have a Person class and an Order class, with foreign keys in the DB. The EF model will mark Person with a List of Orders and Order with a Person instance.
If I want to set the Person for the Order, do I really have to do it with an instance of Person?
Is there not a slimmed down way to do so, say with just a PersonID ?
To assign Person entity to a Order without loading Person entity, you have to do something like this:
var db = new OneToManyEntities();
var Order = new Order { OrderId = 100, OrderName = "Order name" };
Order. PersonReference.EntityKey = new EntityKey("OneToManyEntities.Person ","PersonID",10);
db.AddToOrders(Order);
db.SaveChanges();
Puzzled's answer is correct for EF v1. It's a pain. If you don't mind the extra query, you can set the property succinctly:
int id = 1;
Order.Person = context.Persons.Where(x => x.PersonID == id).FirstOrDefault();
Entity Framework v4 will have "FK Associations", which is a fancy term for directly-settable foreign keys.