I have implemented a LINQ to SQL based RoleProvider, when I assign role to a user following exception is thrown while AddUsersToRoles method is called. I have defined a composite primary key userid & roleId on this table, it still throwing this exception:
Can't perform Create, Update or Delete
operations on 'Table(UsersInRole)'
because it has no primary key.
My LinQ to SQL implementation of AddUsersToRoles method is as follows. It breaks at db.UsersInRoles.InsertOnSubmit(userInRole);
using (RussarmsDataContext db = new RussarmsDataContext())
{
List<UsersInRole> usersInRole = new List<UsersInRole>();
foreach (string username in usernames)
{
foreach (string rolename in rolenames)
{
UsersInRole userInRole = new UsersInRole();
object userId = ProvidersUtility.GetUserIdByUserName(username,applicationName);
object roleId = ProvidersUtility.GetRoleIdByRoleName(rolename,applicationName);
if (userId != null && roleId != null)
{
userInRole.UserId = (Guid)userId;
userInRole.RoleId = (Guid)roleId;
db.UsersInRoles.InsertOnSubmit(userInRole);
}
}
}
try
{
// db.UsersInRoles.InsertAllOnSubmit(usersInRole);
db.SubmitChanges();
}
catch (ChangeConflictException)
{
db.ChangeConflicts.ResolveAll(RefreshMode.OverwriteCurrentValues);
db.SubmitChanges();
}
}
Any help will be appreciated.
Thanks.
LINQ to SQL does not natively support many to many... the joining table has to have two foreign key columns PLUS 1 primary key column with the IDENTITY attribute.
Related
I am trying to update individual records in sqlite database. I know how to Insert and delete records. I'd like to Update an individual record in a similar way to how I am deleting an individual record below. This uses a linq statement to get the record by Asset ID. I'd then like to pass my data to this to update.
I've also included how I insert a new record for reference. Does anybody have an example that they could share?
Delete an existing record
using (SQLiteConnection localconn = new SQLiteConnection(App.FilePath))
{
localconn.CreateTable<Road_Inspections>();
localconn.Table<Road_Inspections>().Where(x => x.Unique_ID == unique_ID).Delete();
}
Insert new record
Road_Inspections lri = new Road_Inspections()
{
ID = id,
Road_ID = Road_ID.Text.ToString(),
Asset_ID = Asset_ID.Text.ToString(),
Defect_Type = txtDefectType.Text.ToString(),
Response = txtResponse.Text.ToString(),
Inspection_Date = DateTime.Now,
};
using (SQLiteConnection conn = new SQLiteConnection(App.FilePath))
{
conn.CreateTable<Road_Inspections>();
int rowsAdded = conn.Insert(lri);
await DisplayAlert("Success", "Inspeciton Saved to Device", "OK");
}
You need a primary Key or Id in your object Announcement to identify your unique object in your database, for example:
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
Since you want to update you have to get the original entry from the database first.
And then you can edit and update it. So, you don't need to delete it before you insert a new one.
In xamarin form you can use nuget sqlite-net-pcl to achieve this.
Please refer to the following code:
public Task<int> SaveItemAsync(TodoItem item)
{
if (item.ID != 0)
{
return Database.UpdateAsync(item);
}
else
{
return Database.InsertAsync(item);
}
}
For more details,you can check: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/data-cloud/data/databases .
And there is a sample included in above document, you can check it here:https://learn.microsoft.com/en-us/samples/xamarin/xamarin-forms-samples/todo/
I am trying to make a login page. When I try to receive the userdata with linq I get an exception because I try to use Parse in my query. I searched a bit online and found out it is because Linq doesn't recognize Parse. From what I understand I have to translate the not recognisable code to code that linq/slq recognises. Since I have just started using linq queries I have no idea how to accomplish this.
My query:
public static UserDetails GetUser(UserDetails userde)
{
var usr = from u in db.Users
join r in db.Roles on u.RoleId equals r.IdRole
where u.Email == userde.Email && u.Active == true
select new UserDetails
{ Firstname = u.Firstname,
Surname = u.Surname,
Email = u.Email,
Function = u.Function,
Password = u.Password,
Salt = u.Salt,
Userroles = (UserRoles)Enum.Parse(typeof(UserRoles), r.Role1)
};
return usr.FirstOrDefault();
}
I checked these articles:
linq to entities does not recognize method
linq to entities does not recognize the methods system object parsesystem type
you should first use FirstOrDefault() and parse it later. Otherwise linq is still trying to build the select-statement. After FirstOrDefault (or ToList,...) you have your result and can then parse it without problems.
Should be something like this:
public static UserDetails GetUser(UserDetails userde)
{
var usr = from u in db.Users
join r in db.Roles on u.RoleId equals r.IdRole
where u.Email == userde.Email && u.Active == true
select new UserDetails { Firstname = u.Firstname,
Surname = u.Surname,
Email = u.Email,
Function = u.Function,
Password = u.Password,
Salt = u.Salt,
// store the database-value in another property
UserrolesUnparsed = r.Role1
};
// get the database-results
UserDetails details = usr.FirstOrDefault();
// parse the database-value and set it to the property you want to
details.Userroles = (UserRoles)Enum.Parse(typeof(UserRoles), details.UserrolesUnparsed);
return details;
}
sure, there are better/cleaner methods, but this is just to explain you.
I am working on ASP.net MVC ...i have made database and now i am using the code below to insert data in the database using View Model class.
But it gives Entity Validation Error on db.savechanges() in user table(as tbl
_user). Please let me know where i am doing mistake.
Code to insert in DB
public string RegisterStudent(RegisterationLoginViewModel svm)
{
tbl_User_Role usr_role = new tbl_User_Role
{
// UserRole_Id=svm.User_Role_id,
RoleName = svm.User_Role,
Dsecription=svm.Description,
OtherDetails=svm.OtherDetails,
};
db.tbl_User_Role.Add(usr_role);
db.SaveChanges();
tbl_User S_Up = new tbl_User
{
FullName = svm.Full_Name,
DOB = svm.Date_of_Birth,
Address = svm.Home_Address,
MobileNumber = svm.Mobile_Number1,
CNIC = svm.CNIC,
Country = svm.Country,
Provience = svm.Provience,
City = svm.City,
UserRole_Id = usr_role.UserRole_Id,
Gender = svm.Gender,
CreatedOn = DateTime.Now,
};
db.tbl_User.Add(S_Up);
db.SaveChanges(); -->**Exception is thrown at this line**
If your UserRole_Id in model tbl_User_Role is not auto generated, then writing this line of code UserRole_Id = usr_role.UserRole_Id giving null because may be it is the Foreign Key of tbl_User table.
Beside, If you have set DatabaseGeneratedOption.Identity then you need to get it's UserRole_Id after saving the usr_role and then assign it to UserRole_Id.
And finally recheck your Required fields are not null and foreign key is getting value.
While trying to delete a record in a database and recreate it afterwards, using LINQ, I get the error: Cannot add an entity that already exists.
Although the record is deleted.
I am initialising my Sales_header object with data I get from a LINQ query in method
SelectOrdersByOrderID(OrderID).
If the OrderID of the Salesheader meets a certain condition, I want to delete the record in the database (Delete(Sales_header SalesHeader)), add additional values to the object and insert a new record in the database (Insert(Sales_header SalesHeader)).
I do not want to update the record, but delete it and recreate it.
Sales_header SalesHeader = new Sales_header();
SalesHeader = SalesHeaderClass.SelectOrdersByOrderID(OrderID) as Sales_header;
if (SalesHeader.OrderID == *certain value*)
{
SalesHeaderClass.Delete(SalesHeader);
SalesHeader.Orderdate = DateTime.Today;
SalesHeader.Ordertime = DateTime.Now;
SalesHeaderClass.Insert(SalesHeader);
}
...
Method in SalesHeaderClass to select the SalesHeader via LINQ
public static object SelectOrdersByOrderID(int OrderID)
{
var Query = (from p in dc.Sales_headers
where p.OrderID.Equals(OrderID)
select p).SingleOrDefault();
return Query;
Method in SalesHeaderClass to insert the SalesHeader via LINQ
public static void Insert(Sales_header SalesHeader)
{
dc.Sales_headers.InsertOnSubmit(SalesHeader);
dc.SubmitChanges();
}
Method in SalesHeaderClass to delete the SalesHeader via LINQ
public static void Delete(Sales_header SalesHeader)
{
var DelOrder = (from p in dc.Sales_headers
where p.OrderID == SalesHeader.OrderID
select p).Single();
dc.Sales_headers.DeleteOnSubmit(DelOrder);
dc.SubmitChanges();
}
What do I have to do to be able to insert the record?
Creating a new object with the same values does not help.
Aside from the question why an update is not suitable.
You need two contexts to first delete the record, and then insert the record. EF keeps all inserts/updates/deletes in memory until you do a SubmitChanges(), so you cannot have two entities with the same ID.
But to execute the whole things as a single transaction, you're going to need a TransactionScope.
using (var scope = new TransactionScope()) {
using (var salesHeader SalesHeader = new Sales_header()) {
// Delete record
...
salesHeader.SubmitChanges();
}
using (var salesHeader SalesHeader = new Sales_header()) {
// Insert record
...
salesHeader.SubmitChanges();
}
// Mark transaction complete
scope.Complete();
}
To fix this issue, use different datacontext for delete and insert operation.
I have two table BuildGroup and table DocumentTemplate. DocumentTemplate table has BuildGroupId as foreign key which is nullable. In a certain senario I update BuildGroupId in DocumentTemplate table.
public bool EditDocTempForBldGrp(int docId, int bldGrpId)
{
try
{
using (ISession session = Document.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
HSDocumentTemplate objDocBO = new HSDocumentTemplate();
objDocBO = GetDocumentDetailsById(docId);
HSBuildGroup objBldGrp = new HSBuildGroup();
if (bldGrpId != 0)
{
objBldGrp.Id = bldGrpId;
}
else
{
//int ? bldid = null;
//objDocBO.HSBuildGroup.Id = null;
//objDocBO.HSBuildGroup.Id = DBNull.Value;
//objDocBO.HSBuildGroup.Id = -1;
}
objDocBO.HSBuildGroup = objBldGrp;
session.Update(objDocBO);
transaction.Commit();
}
}
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
In another senario I need to set BuildGroupId in DocumentTemplate table again to
dbnull.value. I tried with different cases as in else block. It giving the error : Cannot
implicitly convert type 'System.DBNull' to 'int'.
How can I update a foreign key value with NULL? Any help will be appreciated.
A few observations:
You should not assign the Id to a HSBuildGroup object, but instead load the instance via Session.Load() in case the bldGrpId is not 0.
You can just set the build group of a document to null like this:
objDocBO.HSBuildGroup = null;
NHibernate will take care of the rest.
Hope that helps.
Use Session.Load and null as Kay Herzam said.
You must to be sure than the document exist to call session.Load. Example:
public bool EditDocTempForBldGrp(int docId, int bldGrpId)
{
try
{
using (ISession session = Document.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
session.Get<HSDocumentTemplate>(docId).HSBuildGroup
= bldGrpId = 0 ? null : session.Load<HSBuildGroup>(bldGrpId);
transaction.Commit();
}
}
}
This way nhibernate will execute something like,
select ... from DocumentTemplate where DocId = ..;
UPDATE DocumentTemplate SET .... , BuildGroupId = null where DocumentId = XX;
or
select ... from DocumentTemplate where DocId = ..;
UPDATE DocumentTemplate SET .... , BuildGroupId = YY where DocumentId = XX;
Note there is no select for BuildGroup to the database.
If you are not sure about the existence of the build group, your code should look like:
public bool EditDocTempForBldGrp(int docId, int bldGrpId)
{
try
{
using (ISession session = Document.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
session.Get<HSDocumentTemplate>(docId).HSBuildGroup
= session.Get<HSBuildGroup>(bldGrpId);
transaction.Commit();
}
}
}
This way nhibernate will execute something like,
select ... from DocumentTemplate where DocId = ..;
SELECT .... FROM BuildGroup where buildgroupid = ZZ;
UPDATE DocumentTemplate SET .... , BuildGroupId = null where DocumentId = XX;
Get automatically returns null if the object doesn't exist.
Finally you don't need to call Session.Update() this is for reattaching an entity. Everything associated to a Session will be flushed when you commit the transaction.