cannot set obj value from model return - asp.net-mvc

public bool EditNew(News n)
{
News obj = new News();
obj = c.News.Where(p=>p.NewsID == n.NewsID).SingleOrDefault();
obj.NewsTitle = n.NewsTitle;
obj.IsActive = n.IsActive;
obj.IsHot = n.IsHot;
obj.NewsImage = n.NewsImage;
c.SaveChanges();
return true;
}

Not much information to go on, but assuming c is the DbContext object, it looks like you do not have a News object in your DB with the NewsId you are passing in to the EditNew method which results in the LINQ method SingleOrDefault() returning null

Related

Xamarin iOS - Why Can't I Iterate or Fetch by Index on an NSArray?

I am trying to either iterate over an NSArray in Xamarin, or fetch items by index as follows :
try
{
NSData value = (NSData)NSUserDefaults.StandardUserDefaults["accounts"];
NSKeyedUnarchiver unarchiver = new NSKeyedUnarchiver(value);
NSArray valuesDictionary = (NSArray)NSKeyedUnarchiver.UnarchiveObject(value);
foreach (var x in valuesDictionary)
{
}
if (valuesDictionary != null)
{
var accountList = new List<Account>();
int numberOfOrgs = (int)valuesDictionary.Count;
for (int x = 0; x < numberOfOrgs; x++)
{
var org = valuesDictionary[x];
}
}
However the compiler throws errors both for the iteration and the indexing.
foreach (var x in valuesDictionary)
{
}
errors with "foreach statement cannot operate on variables of type 'NSArray' because 'NSArray' does not contain a public instance or extension definition for 'GetEnumerator'"
and
var org = valuesDictionary[x];
errors with "Cannot apply indexing to a type of NSArray".
Can anyone suggest why this is ? In Objective C I think I'd be able to do both of these things.
Thanks !
For anyone in the future that has this problem, although you can't index on an NSArray, you can use the Xamarin method of :
GetItem<type>(index)
e.g
myArray.GetItem<NSObject>(0).
Works like a charm :)

RemoveRange not deleting all records

The following method should delete all old data however, when I did my investigation I found out that some of the data in the database was not delete even though the posted date was within the range. Can someone explain why?
Data That did not get deleted:
19/02/2020
01/04/2020
24/03/2020
public ActionResult DeleteOldData()
{
for(int i = 8; i < 900; i++)
{
DateTime now = DateTime.Now;
var time = now.AddDays(-i).ToString("dd/MM/yyyy").ToString();
db.Data.RemoveRange(db.Data.Where(a => a.PostedDate == time).ToList());
db.SaveChanges();
}
return View();
}
The preferrable comparison operator for this one is just comparing the 2 dates with <= but the dilemma is you're storing the date as a string, hence we can't compare it directly using LINQ, need to do a workaround like below;
Try the code below, try it also without the loop;
DateTime now = DateTime.Now;
var time = now.AddDays(-i).ToString("dd/MM/yyyy").ToString();
var dateList = db.Data.ToList();
List<Data> toDelete = new List<Data>();
foreach(var item in dateList){
if(Convert.ToDateTime(a.PostedDate) <= Convert.ToDateTime(time)){
toDelete.Add(item);
}
}
db.Data.RemoveRange(toDelete);
db.SaveChanges();

Getting data from database and filtering it by nullable string in ASP.Net MVC and Entity Framwork

I have Computers table in my database and it is sent to controller in view model (vm here).
I send some filter with query string and want to filter Computers table data with these filters which is NOT NULL.
For example:
If producer is sent, filter by producer,
If producer and memoryType is sent, filter by producer and memoryType.
Code:
//GET: Product/notebooks
[Route("Product/Notebooks")]
public ActionResult Notebooks(string producer, string os, string memoryType, string memory, string displayType, string processorType, string ram, string vc)
{
ViewBag.Producer = producer;
ViewBag.OS = os;
ViewBag.MemoryType = memoryType;
ViewBag.Memory = memory;
ViewBag.DisplayType = displayType;
ViewBag.ProcessorType = processorType;
ViewBag.RAM = ram;
ViewBag.VC = vc;
var vm = Methods.Methodss.createHIVM();
return View(vm);
}
createHIVM(); method here and working everywhere:
public static HomeIndexVM createHIVM()
{
ProtelEntities dbProtel = new ProtelEntities();
var phones = dbProtel.Phones.ToList();
var producers = dbProtel.Producers.ToList();
var computers = dbProtel.Computers.ToList();
var sliders = dbProtel.Sliders.ToList();
var contact = dbProtel.Contacts.FirstOrDefault();
var memoryTypes = dbProtel.MemoryTypes.ToList();
var memories = dbProtel.Memories.ToList();
var rams = dbProtel.RAM.ToList();
var cameras = dbProtel.Cameras.ToList();
var displaytypes = dbProtel.DisplayTypes.ToList();
var OS = dbProtel.OS.ToList();
var osversions = dbProtel.OSVersions.ToList();
var proCategories = dbProtel.ProCategory.ToList();
var processorTypes = dbProtel.ProcessorTypes.ToList();
var simTypes = dbProtel.SimTypes.ToList();
var vcCategories = dbProtel.VCCategories.ToList();
var vcSubcategories = dbProtel.VCSubcategories.ToList();
var vcMemories = dbProtel.VCMemories.ToList();
var vm = new HomeIndexVM
{
Computers = computers,
Phones = phones,
Producers = producers,
Sliders = sliders,
Contact = contact,
Cameras = cameras,
VCSubcategories = vcSubcategories,
VCMemories = vcMemories,
VCCategories = vcCategories,
SimTypes = simTypes,
DisplayTypes = displaytypes,
Memories = memories,
MemoryTypes = memoryTypes,
OS = OS,
OSVersions = osversions,
ProCategories = proCategories,
ProcessorTypes = processorTypes,
RAMs = rams
};
return vm;
}
In this case I have tu apply many many if conditionals. I don't know how to deal with it
As the old saying goes. "How do you eat an elephant? The same as everything else, one bite at a time."
You've got a big method with conditions that apply to several lookups. Some conditions will apply to several. So break it up. You won't be doing yourself any favors with class and method names like "Methods" and "Methods.Methodss"
public class EquipmentLookupService
{
private readonly AppDbContext _context = null;
public EquipmentLookupService(AppDbContext context)
{
_context = context ?? throw new ArgumentNullException("context");
}
public IEnumerable<Computer> GetComputers(string manufacturer, string processor)
{
var query = _context.Computers.AsQueryable();
if(!string.IsNullOrEmpty(manufacturer))
query = query.Where(x => x.Manufacturer == manufacturer);
if(!string.IsNullOrEmpty(processor))
query = query.Where(x => x.Processor == processor);
return query.ToList();
}
}
Then your controller action changes more to something like:
var vm = new HomeIndexVM
{
Computers = EquipmentLookupService.GetComputers(manufacturer, processor),
Phones = EquipmentLookupService.GetPhones(manufacturer),
// etc...
};
return View(vm);
As a very basic starting example. You can create methods to load each type of lookup and add whatever conditions apply to each lookup.
Linq queries can contain conditional statements like:
query = _context.Computers.Where(x => (manufacturer == null || x.Manufacturer == manufacturer) && (processor == null || x.Processor == processor));
which might seem like less code, however I don't recommend using conditional code like this inside Linq expressions. Firstly, it can be much harder to read and can hide logic errors with misplaced parenthesis or operations. Secondly, it gets built down into SQL leading to larger, more complex SQL statements for conditions that simply don't need to be applied. In the previous example, the conditional check is kept in code, so criteria is only added to the generated SQL statements if they are needed.
The key to writing efficient (fast) Linq is to avoid prematurely executing an expression such as doing a ToList() before adding conditions. This ends up returning a lot of unnecessary data from the database to the server, requiring time and memory before the data is filtered.

How can I get originalvalues from EF savechanges for complex primary key

i've implemented audit log for all my db objects but i'm running into an issue because of a special case.
i have code similar to the following.
private IEnumerable<CDMA_CHANGE_LOG> GetAuditRecords(DbEntityEntry ent, string userId, string primaryKeyId, bool updateFlag, object originalEntity)
{
List<CDMA_CHANGE_LOG> result = new List<CDMA_CHANGE_LOG>();
string changeId = Guid.NewGuid().ToString();
TableAttribute tableAttr = ent.Entity.GetType().GetCustomAttributes(typeof(TableAttribute), false).SingleOrDefault() as TableAttribute;
// Get table name (if it has a Table attribute, use that, otherwise get the pluralized name)
string entityName = tableAttr != null ? tableAttr.Name : ObjectContext.GetObjectType(ent.Entity.GetType()).Name;
var changeTime = DateTime.UtcNow;
if (ent.State == EntityState.Modified)
{
foreach (var prop in ent.OriginalValues.PropertyNames)
{
//we cant use this because getdatabasevalues will error out when there are 2 rows in the db for this primarykey (U,A)
//var originalValue = ent.GetDatabaseValues().GetValue<object>(prop) == null ? "" : ent.GetDatabaseValues().GetValue<object>(prop).ToString();
var currentValue = ent.CurrentValues[prop] == null ? "" : ent.CurrentValues[prop].ToString();
// For updates, we only want to capture the columns that actually changed
var primaryKey = GetPrimaryKeyValue(ent);
if (originalValue != currentValue)
{
result.Add(new CDMA_CHANGE_LOG()
{
USERID = userId,
DATECHANGED = changeTime,
EVENTTYPE = "M", // Modified
ENTITYNAME = entityName,
PRIMARYKEYVALUE = primaryKey.ToString(),
PROPERTYNAME = prop,
OLDVALUE = originalValue,
NEWVALUE = currentValue,
CHANGEID = changeId
});
}
}
}
return result;
}
now i cant use originalValue = ent.GetDatabaseValues().GetValue(prop) because the records have two fields as primary key so i thought i could query the original value manually from the controller and send as
object originalEntity
so i'm wondering how do i cast originalEntity to the current entity
var originalValues = Convert.ChangeType(originalEntity, ent.GetType());
does not work.
i'm finding it difficult to get. thanks for any help.

How to do If statement in Linq Query

I currently have a list that contains the following
CountryCode (string)
CountryStr (string)
RegionStr (string)
RegionID (int)
AreaStr (string)
AreaID (int)
This is a flattened set of linked data (so basically the results of a joined search that ive stored)
The MVC route will only pass one string which I then need to match up to the data at the right level in the heirachy.
So I'm trying to query the CountryStr then if it doesn't produce results the region then the area; but I need to do that bit of the query and for instance...
var datURL = (from xs in myList
//query 1
where xs.RegionStr == rarREF
select new
{
regionID = xs.RegionId,
CountryID = xs.CountryCd
}
//IF theres no results
where xs.AreaStr == rarREF
select new
{
AreaID = xs.AreaID
regionID = xs.RegionId,
CountryID = xs.CountryCd
}
).ToList();
The only way I see of doing this at the moment is running each query separately then checking which returned values and using that one. I'm hoping there's a cleverer, cleaner method.
It won't be very easy to read, but you could do this in a single pass using something like this:
var datURL = (from xs in myList
where xs.RegionStr == rarREF || xs.AreaStr == rarREF
select new
{
AreaID = (xs.AreaStr == rarRef ? xs.AreaID : default(int)),
RegionID = xs.RegionId,
CountryID = xs.CountryId
}
).ToList();
It might also be easier to read the query if it's rewritten slightly:
var datURL = (from xs in myList
let isArea = xs.AreaStr == rarREF
let isRegion = xs.RegionStr == rarREF
where isRegion || isArea
select new
{
AreaID = (isArea ? (int?)xs.AreaID : null),
RegionID = xs.RegionId,
CountryID = xs.CountryId
}
).ToList();
If we save the comparison result, we can reuse it later. I also added a cast to int? to show how you could use a nullable value instead of using 0 as your "no Area" value.
Aren't you looking for or operator? Does this not generate the results you want?
var datURL = (from xs in myList
where xs.RegionStr == rarREF || xs.AreaStr == rarREF
select new
{
AreaID = xs.AreaStr == rarREF ? xs.AreaID : default(int)
regionID = xs.RegionId,
CountryID = xs.CountryCd
}).ToList();

Resources