I have the following code:
internal static bool SaveUOSChangeLog(List<Contracts.DataContracts.UOSChangeLog> values, string user)
{
try
{
using(var ctx = new StradaDataReviewContext2())
{
values.ForEach(u => { u.Username = user; u.Changed = DateTime.Now; });
var test = ctx.UOSChangeLog.Add(values);
ctx.SaveChanges();
return true;
}
}
The thing I want to do Is to save values to the database. However, I get a the following error message:
Here is my Contracts.DataContracts.UOSChangeLog:
public int? Id { get; set; }
public int Accident_nr { get; set; }
public int Refnr { get; set; }
public int Action { get; set; }
public string Old_data { get; set; }
public string New_data { get; set; }
public DateTime SearchedFromDate { get; set; }
public DateTime SearchedToDate { get; set; }
public DateTime Changed { get; set; }
public string Username { get; set; }
public string Comment { get; set; }
And here Is my Services.StradaDataReview2Model.UOSChangeLog that are used as a DbSet
[Table("UOSChangeLog")]
public partial class UOSChangeLog
{
[Required]
public int? Id { get; set; }
public int Accident_nr { get; set; }
[Required]
public int Refnr { get; set; }
[Required]
public int Action { get; set; }
[Required]
public string Old_data { get; set; }
[Required]
public string New_data { get; set; }
[Required]
public DateTime SearchedFromDate { get; set; }
[Required]
public DateTime SearchedToDate { get; set; }
[Required]
public DateTime Changed { get; set; }
[Required]
public string Username { get; set; }
[Required]
public string Comment { get; set; }
}
You're trying to add a list with the Add method which takes a single object, just keep it simple and use a foreach:
using(var ctx = new StradaDataReviewContext2())
{
foreach(var value in values)
{
value.Username = user;
value.Changed = DateTime.Now;
ctx.UOSChangeLog.Add(value);
}
ctx.SaveChanges();
return true;
}
Just use a simple foreach, linq is a querying language, not a modifying language.
Please use addrange method.
db.TheTable.AddRange(TheList)
db.SaveChanges();
You can use Entity Framework's .AddRange method to add a collection of objects to your Db.
MSDN
It will look like:
using(var ctx = new StradaDataReviewContext2())
{
values.ForEach(u => { u.Username = user; u.Changed = DateTime.Now; });
var test = ctx.UOSChangeLog.AddRange(values);
ctx.SaveChanges();
return true;
}
Related
I inherited a C# ASP.Net Core (now .Net 5.0) project with a bunch of entities models like this:
public class Foo
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid ID { get; set; }
[Column(TypeName = "varchar(36)")]
public string CreatedBy { get; set; }
public DateTime CreatedAt { get; set; }
[Column(TypeName = "varchar(36)")]
public string RDoxFindingsID { get; set; }
[Column(TypeName = "varchar(36)")]
public string LastUpdatedBy { get; set; }
public DateTime LastUpdatedAt { get; set; }
public string F001 { get; set; }
...
public class Bar
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid ID { get; set; }
[Column(TypeName = "varchar(36)")]
public string CreatedBy { get; set; }
public DateTime CreatedAt { get; set; }
[Column(TypeName = "varchar(36)")]
public string RDoxFindingsID { get; set; }
[Column(TypeName = "varchar(36)")]
public string LastUpdatedBy { get; set; }
public DateTime LastUpdatedAt { get; set; }
public string Q100 { get; set; }
... <= The same "header" fields (CreatedBy, CreatedAt, etc. etc) are copied/pasted at the top of each different model
So my Create and Edit razor pages have a lot of duplicate code like this:
public class CreateModel : PageModel
{
...
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
Foo.CreatedAt = DateTime.Now;
Foo.CreatedBy = Findings.CreatedBy;
Foo.LastUpdatedAt = DateTime.Now;
Foo.LastUpdatedBy = Findings.CreatedBy;
_context.Foo.Add(Foo);
await _context.SaveChangesAsync();
Bar.CreatedAt = DateTime.Now;
Bar.CreatedBy = Findings.CreatedBy;
Bar.LastUpdatedAt = DateTime.Now;
Bar.LastUpdatedBy = Findings.CreatedBy;
_context.Bar.Add(Bar);
await _context.SaveChangesAsync();
...
Q: Is there any clever way I can refactor my C# code such that I can write ONE method I can call for ANY of these models? Without copying/pasting each of these 4-6 lines over and over for each individual model?
NOTE: I CANNOT change the model. But I can do whatever I want with the "Pages" code.
Here comes interfaces very handy, it's actually main use of them. Define common interface and use it. This should e something like this
class Foo : IEntity
{
public Guid ID { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedAt { get; set; }
public string RDoxFindingsID { get; set; }
public string LastUpdatedBy { get; set; }
public DateTime LastUpdatedAt { get; set; }
}
class Bar : IEntity
{
public Guid ID { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedAt { get; set; }
public string RDoxFindingsID { get; set; }
public string LastUpdatedBy { get; set; }
public DateTime LastUpdatedAt { get; set; }
}
//You can name whatever you want
interface IEntity
{
Guid ID { get; set; }
string CreatedBy { get; set; }
DateTime CreatedAt { get; set; }
string RDoxFindingsID { get; set; }
string LastUpdatedBy { get; set; }
DateTime LastUpdatedAt { get; set; }
}
class Program
{
public static async Task<IActionResult> OnPostAsync(IEntity entity)
{
if (!ModelState.IsValid)
{
return Page();
}
entity.CreatedAt = DateTime.Now;
entity.CreatedBy = Findings.CreatedBy;
entity.LastUpdatedAt = DateTime.Now;
entity.LastUpdatedBy = Findings.CreatedBy;
_context.Foo.Add(entity);
await _context.SaveChangesAsync();
}
static async void Main(string[] args)
{
await OnPostAsync(new Foo());
}
}
I want to know which approach is faster. I have the following class:
public class AccountBalance
{
public long AccountID { get; set; }
public string AccountNumber { get; set; }
[NotRequiredForDataTable]
public IEnumerable<AccountMediaBalance> AccountMediaBalances { get; set; }
}
public class AccountMediaBalance
{
public long AccountID { get; set; }
public long MediaID { get; set; }
public string MediaSerialNumber { get; set; }
public decimal? CashAmount { get; set; }
public int FareID { get; set; }
public bool ShowID { get; set; }
public bool ShareCash { get; set; }
public bool ShareToken { get; set; }
public bool SharePass { get; set; }
public IEnumerable<Token> Tokens { get; set; }
public IEnumerable<Pass> Passes { get; set; }
}
public class Token
{
public long TokenID { get; set; }
public long AccountID { get; set; }
public long MediaProductID { get; set; }
public long MediaID { get; set; }
public long? ActivateByMediaID { get; set; }
public string SerialNumber { get; set; }
public decimal? TransferValue { get; set; }
public DateTimeOffset CreateTime { get; set; }
public DateTimeOffset? ActivateTime { get; set; }
public DateTimeOffset? ExpiryTime { get; set; }
}
public class Pass
{
public long MediaProductID { get; set; }
public long AccountID { get; set; }
public long MediaID { get; set; }
public int ProductID { get; set; }
public long? ActivateByMediaID { get; set; }
public string SerialNumber { get; set; }
public DateTimeOffset CreateTime { get; set; }
public DateTimeOffset? ActivateTime { get; set; }
public DateTimeOffset? ExpiryTime { get; set; }
}
I have a list of AccountBalance data as List<AccountBAlance> and I want to transform data in a way that I want to separate AccountMediaBalance collection in one list, All tokens in one list and all passes in a separate list.
There are two approaches for doing this:
public void SaveAccountBalances(List<AccountBalance> accountBalances)
{
if (accountBalances != null)
{
var mediaBalances = accountBalances.SelectMany(x => x.AccountMediaBalances ??
Enumerable.Empty<AccountMediaBalance>()).ToList();
var tokens = mediaBalances.SelectMany(x => x.Tokens ?? Enumerable.Empty<Token>()).ToList();
var passes = mediaBalances.SelectMany(x => x.Passes ?? Enumerable.Empty<Pass>()).ToList();
}
}
The other approach would be like following:
public void SaveAccountBalances(List<AccountBalance> accountBalances)
{
var mediaBalances = new List<AccountMediaBalance>();
var tokens = new List<Token>();
var passes = new List<Pass>();
if (accountBalances != null)
{
foreach (var item in accountBalances)
{
mediaBalances.AddRange(item.AccountMediaBalances ?? Enumerable.Empty<AccountMediaBalance>());
}
foreach (var item in mediaBalances)
{
tokens.AddRange(item.Tokens ?? Enumerable.Empty<Token>());
passes.AddRange(item.Passes ?? Enumerable.Empty<Pass>());
}
}
}
Performance is a big concern. Can anyone put me in the right direction and let me know which approach is faster and why?
foreach loop uses GetEnumerator directly, while linq creates the query object first and then GetEnumerator. So it is naturally a little bit faster to use foreach loop for a single iteration but it still makes the code look better to use linq.
I grabbed the latest NuGet of NEST and tried to implement simple elastic search. My code do not index an object. IsValid returns false but I have no idea why. Result is also empty.
Here is my snippet of code. I'll be grateful for the help.
public ActionResult Search()
{
var node = new Uri("http://localhost:49997");
var settings = new ConnectionSettings(
node,
defaultIndex: "my-application"
);
var client = new ElasticClient(settings);
var uporabnik = new uporabnik
{
idUporabnik = 99,
ime = "John",
priimek = "Schwarz"
};
var index = client.Index(uporabnik);
if (!index.IsValid)
{
Log.Error("Error when indexing.");
}
var results = client.Search<uporabnik>(s => s.Query(q => q.Term(p => p.priimek, "Novak")));
return View();
}
I tried Console.WriteLine(index.ServerError.Error), but there comes an error: Object reference not set to an instance of an object. So I do not know, what is error message.
Class uporabnik is below.
public partial class uporabnik
{
public uporabnik()
{
this.ocena = new HashSet<ocena>();
this.predmet = new HashSet<predmet>();
this.studentpredmet = new HashSet<studentpredmet>();
}
[Required]
public int idUporabnik { get; set; }
public Nullable<int> vpisnaStevilka { get; set; }
[Required]
[RegularExpression(#"^[A-z]*$"]
public string ime { get; set; }
[Required]
[RegularExpression(#"^[A-z]*$"]
public string priimek { get; set; }
[RegularExpression(#"^[\w\d-\.]+#([\w\d-]+\.)+[\w-]{2,4}$"]
public string email { get; set; }
public string geslo { get; set; }
[Required]
public string mobi { get; set; }
[Required]
[RegularExpression(#"^[MZ]*$"]
public string spol { get; set; }
[RegularExpression(#"^[123]{1}$"]
public Nullable<int> letnikStudija { get; set; }
public System.DateTime datumRegistracije { get; set; }
public System.DateTime zadnjiDostop { get; set; }
public int idVloge { get; set; }
[JsonIgnore]
public virtual ICollection<ocena> ocena { get; set; }
[JsonIgnore]
public virtual ICollection<predmet> predmet { get; set; }
[JsonIgnore]
public virtual ICollection<studentpredmet> studentpredmet { get; set; }
[JsonIgnore]
public virtual vloga vloga { get; set; }
}
I am trying to create a list of customer names that is fetched from a Json call but I get an error:
cannot implicitly convert type System.Collections.Generic.List<char>
to System.Collections.Generic.List<string>
I am using these 2 classes:
Customers:
namespace eko_app
{
static class Customers
{
public static List<CustomerResponse> GetCustomers(string customerURL)
{
List<CustomerResponse> customers = new List<CustomerResponse>();
try
{
var w = new WebClient();
var jsonData = string.Empty;
// make the select products call
jsonData = w.DownloadString(customerURL);
if (!string.IsNullOrEmpty(jsonData))
{
// deserialize the json to c# .net
var response = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(jsonData);
if (response != null)
{
customers = response.response;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return customers;
}
public class BusinessAssociate
{
public string business_associate_id { get; set; }
public string created_by { get; set; }
public DateTime created { get; set; }
public DateTime modified { get; set; }
public bool? deleted { get; set; }
public string business_id { get; set; }
public string identity_id { get; set; }
public string associate_type { get; set; }
public string name { get; set; }
}
public class Identity
{
public string identity_id { get; set; }
public string created_by { get; set; }
public DateTime created { get; set; }
public DateTime modified { get; set; }
public bool? deleted { get; set; }
public string name { get; set; }
public object identity_type { get; set; }
}
public class ChartOfAccount
{
public string chart_of_accounts_id { get; set; }
public DateTime created { get; set; }
public DateTime modified { get; set; }
public string created_by { get; set; }
public string deleted { get; set; }
public string account_id { get; set; }
public string account_name { get; set; }
public string business_id { get; set; }
public string account_category { get; set; }
public string accounts_groups_id { get; set; }
public string cash_equivalent { get; set; }
public string acc_category { get; set; }
public decimal? balance { get; set; }
public decimal? credit_balance { get; set; }
public decimal? debit_balance { get; set; }
public decimal? absolute_balance { get; set; }
public string balance_type { get; set; }
public decimal? raw_balance { get; set; }
public string extended_name { get; set; }
public string normal_balance_type { get; set; }
}
public class CustomerResponse
{
public BusinessAssociate BusinessAssociate { get; set; }
public Identity Identity { get; set; }
public ChartOfAccount ChartOfAccount { get; set; }
}
public class Messages
{
public string msgs { get; set; }
public string errs { get; set; }
}
public class RootObject
{
public List<CustomerResponse> response { get; set; }
public Messages messages { get; set; }
}
}
}
HomeForm:
private void GetCustomerNameList()
{
// get customers
customerURL = "https://eko-app.com/BusinessAssociate/list_associates/1/sessionId:" + sessionID + ".json";
var customers = Customers.GetCustomers(customerURL);
List<string> customerNames = new List<string>();
foreach (var c in customers)
{
customerNames = c.BusinessAssociate.name.ToList(); <--------error thrown here
}
}
The error is thrown at customerNames = c.BusinessAssociate.name.ToList(); on the HomeForm.
What am I doing wrong in creating a list of customer names?
I think you wanted to add all Customer.BusinessAssociate names to list:
foreach (var c in customers)
{
customerNames.Add(c.BusinessAssociate.name);
}
What you originally written converted each name string to char list.
You're assigning a list of chars (string) into a list of strings.
Try something like this outside of the foreach loop:
customerNames = customers.Select(x => x.BusinessAssociate.name).ToList();
This also makes the initialization of cutomerNames redundant.
Instead of foreach use:
customerNames = customers.Select(c => c.BusinessAssociate.name).ToList();
Im trying to get the last record submitted in the db using the repository pattern and MVC. I am attaching the interface and class.And the controller where you can put the code. Please let me know if you need more details. Thanks.
public interface IRequestRepository
{
tblRequest GetCaseId(int caseId);
}
public class RequestRepository: IRequestRepository
{
helpdeskEntities context = null;
public RequestRepository()
{
context = new helpdeskEntities();
}
public string GetCaseId(Ticket ticket)
{
string caseId = string.Empty;
tblRequest tr = context.tblRequests.Where(u => u.CaseID == ticket.CaseID && u.UEmailAddress == ticket.UEmailAddress).SingleOrDefault();
if (tr != null)
{
caseId = tr.CaseID;
}
return caseId;
}
}
public class Ticket
{
public int CaseID { get; set; }
public string Title { get; set; }
[Required]
public string UFirstName { get; set; }
[Required]
public string ULastName { get; set; }
//public string UDisplayName { get; set; }
[Required]
public string UDep_Location { get; set; }
[Required]
public string UEmailAddress { get; set; }
//public string UComputerName { get; set; }
//public string UIPAddress { get; set; }
[Required]
public string UPhoneNumber { get; set; }
[Required]
public string Priority { get; set; }
[Required]
public string ProbCat { get; set; }
//public string IniDateTime { get; set; }
//public string UpdateProbDetails { get; set; }
//public string UpdatedBy { get; set; }
public string InitiatedBy_tech { get; set; }
public string AssignedBy { get; set; }
public string TechAssigned { get; set; }
[Required]
[DataType(DataType.MultilineText)]
public string ProbDetails { get; set; }
}
Controller
public ActionResult CreateTicket(tblRequest td)
{
}
First, you need to upgrade your IRequestRepository and add that method:
(I am assuming you're using EntityFramework for that)
public IRequestRepository
{
Request Latest(Ticket ticket);
}
Next, you need to implement that method in your RequestRepository:
public class RequestRepository : IRequestRepository
{
/* other code here */
public Request Latest(Ticket ticket)
{
// I'm also assuming you're using an auto incremented CaseId
return this.context.tblRequests.OrderByDescending(p => p.CaseId).FirstOrDefault(p => p.UEmailAddress == ticket.UEmailAddress);
}
}
And another thing:
Your IRequestRepository.GetCaseId implementation returns a string while it should return a tblRequest (one would also expect it to return an int Id...)
Anyway, I hope this helps!