How do I code this SQL query in Linq-To-SQL? - asp.net-mvc

I'm new to MVC and its going well but struggling a bit with the back to front SQL etc
select * from aspnet_Users
where Active = 1 and UserId in (select UserId from aspnet_UsersInRoles,aspnet_Roles where aspnet_Roles.RoleId = aspnet_UsersInRoles.RoleId and aspnet_Roles.RoleName = 'Auth Level 1')
Tables and fields are:
aspnet_Users (UserId int, Active bit, eMail varchar)
aspnet_UsersInRoles (UserId, RoleId)
aspnet_Roles (RoleId int, RoleName varchar)
My attempt - but incomplete looks like this so far:
LmsDataContext db = new LmsDataContext();
var AuthUsers = from aspnet_User in db.aspnet_Users
join userinroles in db.aspnet_UsersInRoles on aspnet_User.UserId equals userinroles.UserId
where aspnet_User.Active
select aspnet_User;
Many thanks in advance

Assuming that you have the associations defined in the database (or the designer), you should be able to access via properties the related entities without resorting to explicit joins. The following example is untested, but should put you on the right track. The basic idea is to find if there are any associations where the associated role has the correct name and choose the user if any are found.
var users = db.aspnet_Users
.Where( u => u.Active )
.Any( u => u.aspnet_UsersInRoles
.Any( r => r.aspnet_Roles.RoleName == "Auth Level 1" ) );

Thanks tvanfossen for the prompt reply, I tried to implement your way but could not get it right. I think your approach is neater bu tI got the following to work :
// Loop through all the Users on the System who are in Auth Level 1 Role and Email them
LmsDataContext db = new LmsDataContext();
var AuthUsers = from aspnet_User in db.aspnet_Users
join userinroles in db.aspnet_UsersInRoles on aspnet_User.UserId equals userinroles.UserId
where aspnet_User.Active
&& userinroles.aspnet_Role.RoleName == "Auth Level 1"
select aspnet_User;
Cheers
J

Related

The MVC action controller generates a url with a token for the user to click on and view the page without logging in

I need to send the user a url with a token so that the user can click on that link and view my page without logging in to the system. This user has been created in my system, but has not set a password, I want this user not to see the other pages but only see the page that I allow.
Please help me to come up with a solution in this regard.
Thanks all.
Create one table in your database like below
Insert the entry in this table when you send the link to particular user. As an example, Here I inserted two entries for UserId 10 and 12
Make one procedure or function to validate the token against request.
CREATE PROCEDURE sp_ValidateUserIdAndTokenId
#UserId INT,
#TokenId varchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF ISNULL(#UserId,0) <> 0 AND ISNULL(#TokenId,'') <> ''
BEGIN
IF EXISTS(SELECT 1 FROM UserToken WHERE UserID = #UserId AND TokenID = #TokenId)
BEGIN
Declare #TokenInsertedDateTime AS DateTime
Declare #IsTokenExpired AS Bit
SET #TokenInsertedDateTime = (SELECT TokenInserted FROM UserToken WHERE UserID = #UserId AND TokenID = #TokenId)
-- Here Calculate the token time difference in minutes for one day i.e. 1440 minutes.
SET #IsTokenExpired = (SELECT CASE WHEN DATEDIFF(MINUTE, #TokenInsertedDateTime, GETDATE()+1) > 1440 THEN 0 ELSE 1 END)
SELECT #IsTokenExpired
END
END
END
Now, When request comes in controller's action at that time you have to make a call the database to identify the Token and User in newly created table and determine the request is valid or not(You can also calculate the interval of time for particular token).
[HttpGet]
[AllowAnonymous]
public ActionResult Add(int userId, string tokenId)
{
// Determine the request with tokenId and validate your tokenId
// make the database call of created procedure or function and validate your userid and token here.
return View();
}

Mapping fields to certain users in mvc

I am creating an mvc application in vb.net in which I am trying to map certain fields to certain users so that it is specific to individual users. I have four SQL tables connected that are involved in the mapping. They are UserTable, ClientTable, ProjectTypeTable and IssueTable.
What I am trying to do is this: A user with the ID of one will log on, I get this ID and match it with the userID in the ClientTable to get the correct user for that client. Once I get that I will get the ClientID and match it with the ProjectTypeTable to get the multiple correct projectTypes, eg a client can have 1-8 projects available to them. The IssueTable will have the selected projectType.
I have created a ViewModel which looks like this:
Public Class ClientViewModel
Public proTable As List(Of ProjectType)
Public cTable As ClientTable
Public uTable As UserTable
Public iTable As IssueTable
End Class
What I planned to do is retrieve the userID when the user logs on and pass it to other views in session state so that the correct userID is kept through out the project until they log out. Here is what I have tried:
Dim uTable As SQLDatabase = New SQLDatabase()
Dim getUserID = (From data In uTable.UserTables Where data.username = user.username AndAlso data.userPassword = user.userPassword Select data.userID)
If (getUserID .Count() > 0) Then
Session("userIDData") = getUserID.ToString()
Then in the submit controller I have this:
Dim getuserID = Session("userIDData")
Dim userModel = New IssueTracker.ClientViewModel()
userModel.cTable = dbServer.ClientTables.Where(Function(x) x.userID = "")
'the speech marks will be the userID retrieved from the session state
userModel.proTable = dbServer.ProjectTypes.Where(Function(x) x.client = "").ToList()
'the speech marks will be the clientID retrieved from the session state
The problem I am having is that I am not actually getting the ID, is this a good way to map the users to specific fields? The ID's do not have to be sent across via session state that was the last thing I tried. How can I do this correctly?

SubmitChanges doesn't always update database

I am using ASP.NET MVC 4 (.NET framework 4.5) with LINQ-to-SQL and SQL Server 2008 R2
This function returns always true if I run it through debug mode, but when I run it without debug, it returns false. I once got this error: http://i.imgur.com/HydhT.png
I tried googling this, some similiar problems came up but I checked them all:
UserProfiles table has a primary key
The datacontext is in sync with the database
I've tried putting ConflictMode.ContinueOnConflict as an argument in SubmitChanges()
I've tried to put above the facebookID in LINQ designer: UpdateCheck=UpdateCheck.Never
Nothing works. I have never experienced anything like this before. Does anyone have any idea?
Code:
facebookID field in SQL Server is varchar(50) NULL with default value NULL
public static bool changeFacebookIDByEmail(string email, string facebookID)
{
UserProfile profile = (from s in _dc.Users
join u in _dc.Memberships on s.UserId equals u.UserId
join i in _dc.UserProfiles on u.UserId equals i.userID
where u.Email == email
select i).SingleOrDefault();
profile.facebookID = facebookID;
ChangeSet cs = _dc.GetChangeSet();
_dc.SubmitChanges();
if (cs.Updates.Count <= 0)
return false;
else
return true;
}
It seems like you are executing a manual SQL statement:
UPDATE UserProfiles SET facebookID = NULL WHERE userID = '85A6D951-15C8-4892-B17D-BD93F3D0ACBB'
This will set the facebookID to null. Entity framework does not know this, though. It cannot interpret raw SQL. So it still thinks the facebookID is set to some value. When you later set it to that value in changeFacebookIDByEmail EF thinks nothing changed.
Sou you probably should not execute raw SQL strings. Use EF to change the value to null.
Change .singleordefault to .single I think your problem will be revealed pretty soon after that.
Basically anything found by your query with be in the datacontext. Anything new eg default will not.
You need to rewrite your routine to insert the new user in the case where it's not found.
EDIT
This is some code from a project I have been working on. I've cut out a bunch of stuff to demonstrate how it should work.
// add the identity as necessary
var found = dB.Identities.SingleOrDefault(q => q.UserName == userName);
if (found == null)
{
found = new Identity
{
Domain = domain,
Password = User.Identity.AuthenticationType,
Salt = "",
UserName = userName,
LastUpdatedDateTime = DateTime.Now
};
dB.Identities.InsertOnSubmit(found);
}
dB.SubmitChanges(null);

Updating a many to many collection with EF code first

I'm using EF Code First with the following configuration
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<UserProfile>()
.HasMany(x => x.TeamLeaders)
.WithMany()
.Map(m => m.MapLeftKey("UserId")
.MapRightKey("TeamLeaderId")
.ToTable("UserTeamLeaders"));
}
TeamLeaders is an ICollection of Users i.e. it is a self referencing many-many relationship.
In plain English, a user can have more than one team leader. This configuration appears to be correct, as it creates the duel FK/PK link table as I would expect.
I have an MVC4 application that allows editing, adding and removal of team leaders from the collection.
In my controller, I originally had the following:
var original = context.UserProfiles
.Include("TeamLeaders")
.Single(x => x.UserId == model.UserId);
context.Entry(original).CurrentValues.SetValues(model);
However, that last line was failing to mark the TeamLeaders collection as updated, and when I called SaveChanges(), no changes were recorded.
Instead I wrote a simple CopyProperties method on my User class, which uses reflection to manually copy the properties across, so in my controller I now have:
var original = context.UserProfiles
.Include("TeamLeaders")
.Single(x => x.UserId == model.UserId);
//context.Entry(original).CurrentValues.SetValues(model);
original.CopyProperties(model);
However, this goes too far, and SaveChanges attempts to add a new user to the system matching the profile of the selected team leader.
Can anyone advise as to which part of this I am doing wrong? I am not sure whether I need to update the mappings, or change the way I copy properties from the view model to the model
You must modify the loaded TeamLeaders collection in the original user according to your changes so that change detection can recognize which leaders have been removed and which have been added. When you call SaveChanges then EF will write the appropriate DELETE and INSERT statements for the join table based on the detected changes. The simplest way would look like this:
var original = context.UserProfiles
.Include("TeamLeaders")
.Single(x => x.UserId == model.UserId);
original.TeamLeaders.Clear();
foreach (var teamLeader in model.TeamLeaders)
{
var user = context.UserProfiles.Find(teamLeader.UserId);
if (user != null)
original.TeamLeaders.Add(user)
}
context.SaveChanges();
Find will fetch the team leaders from the context if they are already loaded. If they aren't loaded it will query the database.
If you want to avoid additional queries you can attach the team leaders manually to the context:
var original = context.UserProfiles
.Include("TeamLeaders")
.Single(x => x.UserId == model.UserId);
original.TeamLeaders.Clear();
foreach (var teamLeader in model.TeamLeaders)
{
var user = context.UserProfiles.Local
.SingleOrDefault(o => o.UserId == teamLeader.UserId);
if (user == null)
{
user = new User { UserId = teamLeader.UserId };
context.UserProfiles.Attach(user);
}
original.TeamLeaders.Add(user)
}
context.SaveChanges();
Except the first query to load the original here is no further database query involved.
BTW: You should be able to use the strongly typed Include version with EF Code First:
Include(u => u.TeamLeaders)
You just need using System.Data.Entity; in your code file to get access to this version.

Update Data return Cannot insert duplicate key row in object

I'm working with Entity Framework and the structure for my DB is something like this:
An user have a collections of subscribers, so...
Subscriber:
Name
UserId
User (to navigate on user object)
if I get the subscriber without the user, I modify the "name" and commit the changes and all works fine, but if I get the subscriber with the user instanciated, in the CommitAndRefreshChanges, throws me:
Cannot insert duplicate key row in object 'dbo.User' with unique index 'PK_Email'.\r\nThe statement has been terminated
but I don't change anything for user... what I'm doing wrong?
To get the subscriber I run on the repository:
RegistrationModuleDataModelContainer context = UnitOfWork as RegistrationModuleDataModelContainer;
Subscriber subscriber = (from s in context.Subscribers.Include(it=>it.User)
where s.IdSubscriber == idSubscriber
select s).FirstOrDefault();
To modify the data use the next code:
Subscriber subscriber = this.GetSubscriberWithUser(idSubscriber);
subscriber.FirstName = FirstName;
subscriber.LastName = LastName;
//Condition with subscriber.User.x
subscriber.Email = Email;
_subscriberRepository.Modify(subscriber);
IUnitOfWork unitOfWork = _subscriberRepository.UnitOfWork;
unitOfWork.CommitAndRefreshChanges();
If I erase the condition, fails anyway, the problem is when I load the subscriber with the user, if I load the subscriber only, the commit works.
Thanks!

Resources