Reputation: 91666
I have a table called TPM_TASKS
which contain all tasks, as well as a table called TPM_USER
which contains all users. I then have a table called TPM_USERTASKS
which contains a UserId
and TaskId
which stores the assignment of one task to one user.
I'm attempting to select all tasks that are assigned to a given TPM_USER
entity. So far, I've tried:
TPM_USER user = UserManager.GetUser(context, UserId); //Lookup the user in the DB
var tasks = (from t in context.TPM_TASK.Include("TPM_USER")
where t.TPM_USER.Contains<TPM_USER>(user)
select t);
However, when I try to iterate into this I get the runtime exception:
Unable to create a constant value of type 'Entity.TPM_USER'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
I believe it doesn't like me passing in a TPM_USER object into Contains()
. This probably makes sense, as it would have to generate a nested SELECT statement rather than an IN
clause, which perhaps EF isn't capable of doing. However, surely there's a way to do a query like this, right?
NOTE: If you're clever, you're probably about to ask me why I don't just query TPM_USERTASKS
and then join in the matching TPM_TASK
instead. Well, I'd love to do this. However, I've been trying all morning to get EF to generate a TPM_USERTASK model and it simply won't. The table shows up in the model store, and I can define relationships against it. It doesn't show up in the list of entities I can add or refresh from the database, and I've even tried deleting the entire .EDMX file and creating it again. I'm guessing something that gets used in a many-to-many relationship can't also be a stand-alone entity?
Upvotes: 0
Views: 290
Reputation: 60503
Well, you've got to use Navigation properties.
In a many-to-many relation, this means that you must have a
public virtual ICollection<TPM_USER> TpmUsers {get;set;}
in your TPM_TASK class
and /or a
public virtual ICollection<TPM_TASK> TpmTasks{get;set;}
in you TMP_USER class.
If you don't, you won't be able to write a query joining the two entities.
With that, you can write your query as
var userTasks = context.TPM_TASK
.Where(task => task.TpmUsers
.Any(user => user.Id == UserId));
Upvotes: 2
Reputation: 3971
Your query would look something like this:
var tasks = (from t in context.TPM_TASK.Include("TPM_USER")
where t.TPM_USER.Any(x => x.Id == user.Id)
select t);
But that's somehow a little bit off anyway. The TPM_USER object should already have a reference to TPM_TASK. So user.TPM_TASKS should give you all the tasks of the given user, otherwise your model is somehow wrong.
TASKS many-to-many USERS means: One Task, many users. One user, many Tasks.
Or am I wrong?
Update:
If you really want to get the TPM_USERTASKS class in your model you'd have to add a separate Key/Id to it.
create table TPM_USERTASKS (
ID int identity(1,1) not null
UserId int not null,
TaskId int not null,
constraint [PK_TPM_USERTAKS] primary key (ID)
)
Upvotes: 2