SQLLITE-Xamarin Form - How to check if a value already exist - c#

I looking to check if a value already exists, if exists return true if not false. However, I may be missing something on my logic because is always returning null even if the value exists
sample
public bool ExistPref(int userid)
{
var result = prefDB.db.Table<notificationsPreferences>().Where(t => t.UserId == userid).FirstOrDefault();
Console.WriteLine("user exist "+result+userid);
return result != null;
}
and if the user exist
I would like to update his record otherwise insert the new values
public int UpdateNotifications(notificationsPreferences item)
{
if (item.UserId != 0)
{
return prefDB.db.Update(item);
}
else
{
return prefDB.db.Insert(item);
The issue is here ** the Id comes inside the object item, however for some reason doesn't save the 4 digits id, what gets saved is for example 4 which I assumed is the times I add this item?/ that's why my result is always false because it is not saving the real id .
}
}

use Any
return prefDB.db.Table<notificationsPreferences>().Any(t => t.UserId == userid);

if the user exist I would like to update his record otherwise insert the new values
If you want to insert new record or update record into sqlite, you can take a look the following code:
private void insertorupdate(User model)
{
var data = _SQLiteConnection.Table<User>();
var d1 = data.Where(x => x.userId == model.userId).FirstOrDefault();
if (d1 == null)
{
_SQLiteConnection.Insert(model);
Console.WriteLine("Sucessfully Added");
}
else
{
Console.WriteLine("Already Mail id Exist");
_SQLiteConnection.Update(model);
}
}
public class User
{
[PrimaryKey, AutoIncrement]
public int userId { get; set; }
public string userName { get; set; }
public string password { get; set; }
}

Related

Problem with selecting from database to complex type using EF Core

I try to use complex type if EF Core.
my table structure
source code
User
-----------
Id (uniqueidentifier)
FirstName (nvarchar(255))
LastName (nvarchar(255))
and my class strcuture is
public class UserId
{
public Guid Value { getl }
private UserId() { }
public UserId (Guid newId) {
//check and assign
}
}
public class User
{
public UserId Id { get; }
public Name Name { get; }
private User() { }
public User(Name name) {
//.... anti corruption
}
}
public class Name
{
public string First { get; }
public string Last { get; }
private Name() { }
public Name(string firstName, string lastName)
{
//anti curruption
}
}
and here is OnModelCreating
modelBuilder.Entity<User>()
.ToTable("User");
modelBuilder.Entity<User>()
.HasKey(u => u.Id);
modelBuilder.Entity<User>()
.OwnsOne(u => u.Name, un =>
{
un.Property(x => x.First).HasColumnName("FirstName");
un.Property(x => x.Last).HasColumnName("LastName");
});
every thing is work fined when I created a User and Save to database
but when I try to read it from database. the Name property is null
but again when I use .AsNoTracking. It work fined.
(I got from exception but I can't remember how to did it again)
MyDbContext db = new MyDbContext();
var newUser = new User(name: new Name("Foo", "Fighter"));
db.Users.Add(newUser);
db.SaveChanges();
var u1 = db.Users.Take(1).First();
PrintResult("Case 1", u1); //output > Could not read Name from database
var u2 = db.Users.AsNoTracking()
.Take(1).First();
PrintResult("Case 2", u2); //output > Read Name from database success
Console.Read();
my print result method
static void PrintResult(string label, User u)
{
Console.WriteLine($"{label} >>>>>");
if (u.Name == null)
{
Console.WriteLine("Could not read Name from database");
}
else
{
Console.WriteLine("Read Name from database success");
}
}
Can someone tell me that did I do something wrong ?
Why I have to use .AsNoTracking ?
In fact the issue does not reproduce with the posted model here. But it does with the one from the link, and the difference is the type of the PK property in the model - there is no problem when using well known primitive type, but you are using custom id class - yet another DDD "sugar", but with improper/missing equality implementation.
Without implementing value semantics for your id class, EF Core will compare it by reference, thus not finding the "owner PK" needed by the owned entity type. The no tracking queries have no such search, that's why it is "working".
The correct action is to implement value equality semantics in your UserId class (used as a type of User.Id property)
public class UserId
{
public Guid Value { get; }
protected UserId() { }
public UserId(Guid id)
{
if (id == Guid.Empty)
throw new ArgumentException("UserId must not be Empty");
Value = id;
}
}
for instance by adding
public override int GetHashCode() => Value.GetHashCode();
public override bool Equals(object obj) => obj is UserId other && Value == other.Value;

Linq to SQL column computed from query to different table?

Is it possible to define a column in one of my Linq to SQL entities such that it's calculated as part of the SQL query?
Here is my Entity class so far:
[Table(Name = "Products")]
public class ProductEntity
{
[Column(Name = "ModelNumber", IsPrimaryKey = true)]
public string ModelNumber { get; set; }
[Column(Name = "SerialNumber", IsPrimaryKey = true)]
public string SerialNumber { get; set; }
}
I want to add a new property like:
[Column]
public bool ActiveListing { get; set; }
Except its value should be calculated based on a complicated Linq query which I am executing elsewhere right now (not in SQL!):
context.GetTable<SalesRecords>().
Where(ah => ah.Date <= GlobalCoordinatedDateTime.Local).
Where(ah => ah.ProductModelNumber == ModelNumber && ah.ProductSerialNumber == SerialNumber).
OrderByDescending(ah => ah.Date).
FirstOrDefault().Status == Statuses.Active;
My best guess is that I could use AssociationAttribute but I don't know how to do that when there could be more than one match in the "SalesRecords" table and I want to get the first after applying some ordering.
EDIT: My question is not the same as a simple "computed column" as seen in this question, I need to compute the value using data stored in different tables, outside of the entity its self.
if you don't need to store the column at database you can use:
[Table(Name = "Products")]
public class ProductEntity
{
// your other columns...
[NotMapped]
public bool ActiveListing {
get
{
bool result = false;
// your logic to calculate then set to "result" variable
return result;
}
}
}
but if you need to store it, change the name of ActiveListing property, then manually assign to the final ActiveListing property before you will create or update the record. Example:
[Table(Name = "Products")]
public class ProductEntity
{
// your other columns...
[NotMapped]
public bool CalculateActiveListing
{
get
{
bool result = false;
// your logic to calculate then set to "result" variable
return result;
}
}
public bool ActiveListing { get; set; }
}
here an example if you have a navigation property to SalesRecords. important have Lazy Loading enabled, or use the Include() method.
[NotMapped]
public bool CalculateActiveListing
{
get
{
bool result = false;
// your logic to calculate then set to "result" variable.
// for example:
// validate SalesRecords has data
if (this.SalesRecords != null)
{
var sale = this.SalesRecords
.Where(ah => ah.Date <= GlobalCoordinatedDateTime.Local)
.Where(ah => ah.ProductModelNumber == ModelNumber && ah.ProductSerialNumber == SerialNumber)
.OrderByDescending(ah => ah.Date)
.FirstOrDefault();
// sale exists
if (sale != null)
{
result = sale.Status == Statuses.Active;
}
}
return result;
}
}
another example using your DbContext:
[NotMapped]
public bool CalculateActiveListing
{
get
{
bool result = false;
// your logic to calculate then set to "result" variable.
// for example:
using (var context = new MyDbContext())
{
var sale = context.SalesRecords
.Where(ah => ah.Date <= GlobalCoordinatedDateTime.Local)
.Where(ah => ah.ProductModelNumber == ModelNumber && ah.ProductSerialNumber == SerialNumber)
.OrderByDescending(ah => ah.Date)
.FirstOrDefault();
// sale exists
if (sale != null)
{
result = sale.Status == Statuses.Active;
}
}
return result;
}
}
sorry, my bad english.

Create or update if item exist

I have a create form where if the specific Medicine exist, its number of supply will update or added with the new entry however if the specific Medicine doesn't exist, it will create a new batch of data.
Im having trouble at understanding how update works in MVC.
Here is the error:
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded.
Here is my controller:
public ActionResult Create([Bind(Include = "SupplyID,MedicineID,Expiration,NumberOfSupply")] Supply supply)
{
if (ModelState.IsValid)
{
bool supplyExsist = db.Supplies.Any(x => x.Expiration == supply.Expiration && x.MedicineID == supply.MedicineID);
if (supplyExsist)
{
var currentSupply = (from x in db.Supplies //get current supply
where x.MedicineID == supply.MedicineID
&& x.Expiration == supply.Expiration
select x.NumberOfSupply).First();
db.Entry(supply).State = EntityState.Modified;
supply.NumberOfSupply = currentSupply + supply.NumberOfSupply;
db.SaveChanges();
return RedirectToAction("Index");
}
else
{
db.Supplies.Add(supply);
db.SaveChanges();
return RedirectToAction("Index");
}
}
ViewBag.MedicineID = new SelectList(db.Medicines, "MedicineID", "MedicineName", supply.MedicineID);
return View(supply);
}
Model:
public class Supply
{
[Key]
public int SupplyID { get; set; }
[ForeignKey("Medicine")]
public int MedicineID { get; set; }
public Medicine Medicine { get; set; }
[DataType(DataType.Date)]
public DateTime Expiration { get; set; }
[Display(Name = "Quantity")]
[Range(1, int.MaxValue, ErrorMessage = "The value must be greater than 0")]
public int NumberOfSupply { get; set; }
}
just try this
db.Supplies.AddOrUpdate(h => h.medicineID,supply));
it will check if there is a row with the same medicine ID in db if not it adds a new one else it updates it
You should change your if block with following :
if (supplyExsist)
{
var currentSupply = (from x in db.Supplies //get current supply
where x.MedicineID == supply.MedicineID
&& x.Expiration == supply.Expiration
select x.NumberOfSupply).First();
db.Supplies.Attach(supply);
db.Entry(supply).State = EntityState.Modified;
supply.NumberOfSupply = currentSupply + supply.NumberOfSupply;
db.SaveChanges();
return RedirectToAction("Index");
}

PUT does not insert object in SQL Server

I'm having a problem with Web API where I want to create a new object in SQL Server.
The PUT method is used to update an expensenote. An expensenote contains dailyexpensenotes. A dailyexpensenote contains individualexpenses.
In the GUI, a user that edits his expensenote can:
Fill in an empty individualexpense with value > 0 (Creates a new individualexpense)
Change an existing individualexpense (Updates the existing individualexpense)
Clear an individualexpense/change value to 0 (Deletes the existing individualexpense)
After this the user clicks save and the entire expensenote is sent by ajax call to the web service. Nr 2 and Nr 3 are working as desired but the Nr 1 doesn't work and gives no error.
PUT method
// PUT api/expenses/5
public void Put(int id, [FromBody]Expensenote exUpdate)
{
expensenote ex = (from e in db.expensenotes
where e.ID == id
select e).FirstOrDefault();
if (ex == null)
{
//return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Request was not found.");
}
else
{
foreach (Expensenotedaily d in exUpdate.dailyExpenses)
{
var daily = ex.expensenotedailies.SingleOrDefault(da => da.ID == d.ID);
daily.city = d.city;
daily.dailyallowance = d.dailyallowance;
foreach (Expenseindividual i in d.individualExpenses)
{
expenseindividual individual = daily.expenseindividuals.SingleOrDefault(ind => ind.ID == i.ID);
if (i.value == 0)
{
if (!(individual == null))
{
db.expenseindividuals.Remove(individual);
}
}
else
{
if (!(individual == null))
{
individual.value = i.value;
}
else
{
expenseindividual newInd = db.expenseindividuals.Create();
newInd.typecode_ID = i.expensetypeID;
newInd.daily_ID = daily.ID;
newInd.typecode = db.typecodes.SingleOrDefault(t => t.ID == i.expensetypeID);
newInd.expensenotedaily = daily;
newInd.value = i.value;
newInd.creditcard = false;
db.expenseindividuals.Add(newInd);
//SOLUTION: db.SaveChanges();
}
}
}
}
db.SaveChanges();
}
}
expenseindividual datamodel class
public partial class expenseindividual
{
public expenseindividual()
{
this.supplementalinfoes = new HashSet<supplementalinfo>();
}
public int ID { get; set; }
public double value { get; set; }
public bool creditcard { get; set; }
public int daily_ID { get; set; }
public int typecode_ID { get; set; }
public virtual expensenotedaily expensenotedaily { get; set; }
public virtual typecode typecode { get; set; }
public virtual ICollection<supplementalinfo> supplementalinfoes { get; set; }
}
When I debug I see that all attributes are passed correctly.
Using newInd = new expenseindividual() instead of Create() doesn't fix the problem.
I tried setting the expenseindividual.ID manually and this makes the insert work but it must auto increment and auto increment is enabled.
So I'm really wondering what causes the problem here and how I can fix it?
If I understand you correctly, you are trying to insert a new expense note into the database when one does not already exist?
Firstly... this code currently ignores expense notes that do not already exist in the database...
expensenote ex = (from e in db.expensenotes
where e.ID == id
select e).FirstOrDefault();
if (ex == null)
{
//return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Request was not found.");
}
else
{
ex will always be null when you pass an id of an expense note that does not already exist inside of the database, therefore no code will be run.
The convention is that typically PUT is always used to update a record, POST is used instead when trying to create one but thats up to you.
You need to implement your logic to create a new record within the if statement, replacing the commented out return statement.

Disable username validation on edit

I created my validation for unique username and now I can't edit my user. It's saying that username is already taken which makes sense since it's taken by the user that I'm trying to edit. I don't even want to edit username but because of this error I cannot edit any other field as well.
How can I disable unique username validation for my EDIT action?
Validator
public override bool IsValid(object value)
{
if (value == null) return false;
FinanceDataContext _db = new FinanceDataContext();
var user = _db.Users.ToList().Where(x => x.Username.ToLower() == value.ToString().ToLower()).SingleOrDefault();
if (user == null) return true;
return false;
}
Action
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(User u)
{
// Get user we want to edit
var user = _db.Users.Where(x => x.ID == u.ID).SingleOrDefault();
if (user == null) return HttpNotFound();
// Set values and save changes
user.Address = u.Address;
if (!string.IsNullOrEmpty(u.Password)) user.Password = Infrastructure.Encryption.SHA256(u.Password);
_db.SaveChanges(); // validation error
return null;
}
Model
public class User
{
public int ID { get; set; }
[Required]
[UniqueUsername(ErrorMessage = "Username is already taken")]
public string Username { get; set; }
[Required]
public string Password { get; set; }
public string Address { get; set; }
}
Error
Validation failed for one or more entities. See
'EntityValidationErrors' property for more details.
Pass the "ID" property in "AdditionalFields" parameter of UniqueUsername Attribute so I guess your code should be like this
Class Property :
[Required]
[UniqueUsername(ErrorMessage = "Username is already taken", AdditionalFields = "ID")]
public string Username { get; set; }
Validate Action :
public ActionResult UniqueUsername(string userName, int id)
{
FinanceDataContext _db = new FinanceDataContext();
var user = _db.Users.ToList().SingleOrDefault(x => x.Username.ToLower() == value.ToString().ToLower() && x.ID != id);
return Json(user == null, JsonRequestBehavior.AllowGet);
}
Hope this will help !!
Could you pass in the user id into the IsValid method and make sure the user returned doesn't have the same user id?
One thing I would like to contribute.
This code:
var user = _db.Users.ToList().Where(x => x.Username.ToLower() == value.ToString().ToLower()).SingleOrDefault();
Is not performatic, because when you do a ToList() you execute the whole query. In this case, what you are doing is retrieving ALL USERS from the database and them doing your filter in memory.
I would sugest you to do this:
_db.Users.Where(x => x.Username.ToLower() == value.ToString().ToLower()).SingleOrDefault();
Since you just want to retrieve one record, there is no need to call the ToList() method. Just the SingleOrDefault() at the end is enough.
Fixed it by passing whole object to my validator and then checking id's as well as usernames.
public override bool IsValid(object value)
{
var user = (User)value;
if (user == null) return true;
FinanceDataContext _db = new FinanceDataContext();
var u = _db.Users.Where(x => x.Username.ToLower() == user.Username.ToLower() && x.ID != user.ID).SingleOrDefault();
if (u == null) return true;
return false;
}

Categories