I wrote very simple class, that perfom data access.
It checks if line with that day exist in table and update her or create a new line.
public class DataAccessClass
{
public static DayWeather GetDayWeather(DateTime date)
{
try
{
using (var db = new Context())
{
var query =
(from day in db.DayWeather
where ((DateTime)day.DateOfDay).Date == date.Date
select new DayWeather((short)day.Temperature, (ushort)day.WindSpeed, (ushort)day.Pressure, (ushort)day.Humidity, day.Cloudiness, day.TypeRecip, (DateTime)day.DateOfDay)).First();
return query;
}
}
catch (Exception exp)
{
if (!EventLog.SourceExists("DataAccessSource"))
{
EventLog.CreateEventSource("DataAccessSource", "DataAccessErrorLog");
}
EventLog.WriteEntry("DataAccessSource", exp.Message);
throw new Exception("Problem with data get.");
}
}
public static void SaveDayWeather(DayWeather day)
{
try
{
using (var db = new Context())
{
var existingDay =
(from d in db.DayWeather
where ((DateTime)day.DateOfDay).Date == day.DateOfDay.Date
select d).SingleOrDefault<DayWeather>();
if (existingDay != null)
{
existingDay.Temperature = day.Temperature;
existingDay.WindSpeed = day.WindSpeed;
existingDay.Pressure = day.Pressure;
existingDay.Humidity = day.Humidity;
existingDay.Cloudiness = day.Cloudiness;
existingDay.TypeRecip = day.TypeRecip;
db.SaveChanges();
}
else
{
DayWeather newDay = new DayWeather();
newDay.DateOfDay = day.DateOfDay;
newDay.Temperature = day.Temperature;
newDay.WindSpeed = day.WindSpeed;
newDay.Pressure = day.Pressure;
newDay.Humidity = day.Humidity;
newDay.Cloudiness = day.Cloudiness;
newDay.TypeRecip = day.TypeRecip;
db.DayWeather.Add(newDay);
db.SaveChanges();
}
}
}
It use EF for generate database. The Contex class and class for save look like this:
public class DayWeather
{
public short Temperature { get; set; }
public ushort WindSpeed { get; set; }
public ushort Pressure { get; set; }
public ushort Humidity { get; set; }
public string Cloudiness { get; set; }
public string TypeRecip { get; set; }
public DateTime DateOfDay { get; set; }
public DayWeather(short Temperature, ushort WindSpeed, ushort Pressure, ushort Humidity, string Cloudiness, string TypeRecip, DateTime Date)
{
this.Temperature = Temperature;
this.WindSpeed = WindSpeed;
this.Pressure = Pressure;
this.Humidity = Humidity;
this.Cloudiness = Cloudiness;
this.TypeRecip = TypeRecip;
this.DateOfDay = Date;
}
public DayWeather()
{
}
}
internal class Context : DbContext
{
public DbSet<DayWeather> DayWeather { get; set; }
}
I call this methods by this code:
DataAccessClass.SaveDayWeather(new DayWeather(12, 12, 12, 12, "Yes", "rain", DateTime.Now));
DayWeather day = DataAccessClass.GetDayWeather(DateTime.Now);
Console.WriteLine(day.ToString());
Console.ReadKey();
It should generate new database, but error occurs. In message it write that can`t connect to the SQL Server.
Is somebody know what is wrong?
P.S. Sorry for my bad English.
P.P.S. I added EF by NuGet.
You can manually specify the connection string as follows
using (var db = new Context("connectionString"))
The default constructor looks up a connection string in the web.config with the same name as the derived context class Context.
If it fails to find one it defaults to
Data Source=.\SQLEXPRESS;
or
Data Source=(LocalDb)\v11.0;
depending on the version of sql server you are using.
Related
I am new to using CSVHelper and AutoMapper and am getting the following error when trying to:
public async Task<IActionResult> OnPostAsync()
{
if (BolCsv != null)
{
try
{
using (var reader = new StreamReader(BolCsv.OpenReadStream()))
using (var csvr = new CsvReader(reader, System.Globalization.CultureInfo.CurrentCulture))
{
csvr.Configuration.Delimiter = "\t";
csvr.Configuration.HeaderValidated = null;
csvr.Configuration.MissingFieldFound = null;
var bolDtos = csvr.GetRecords<BOLDto>().ToList();
var bols = _mapper.Map<IEnumerable<BOL>>(bolDtos);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
var bolDtos = csvr.GetRecords<BOLDto>();
Error: No members are mapped for type 'BOLDto'.
BOLDto:
{
public class BOLDto
{
[Name("BOLNumber")]
public int BOLNumber { get; set; }
[Name("ProductID")]
public int ProductID { get; set; }
[Name("ProductDescription")]
public string ProductDescription { get; set; }
etc...
}
}
BOL.cs:
{
public class BOL
{
public int BOLNumber { get; set; }
public int ProductId { get; set; }
public string ProductDescription { get; set; }
etc...
}
}
As I mentioned Im new to ASP.Net Core AutoMapper, and CSVHelper... how do I solve this issue?
It looks like your BOLDto class has properties, but that error message is the same as I would get if the class had fields instead of properties. So you might want to try CsvHelper.Configuration.MemberTypes.Fields. Also that must be an older version of CsvHelper you are using, because that is not how you would need to set up the configuration in the current version. But it should still work for you to add csvr.Configuration.MemberTypes = CsvHelper.Configuration.MemberTypes.Fields.
void Main()
{
var config = new MapperConfiguration(cfg => cfg.CreateMap<BOLDto, BOL>());
var _mapper = config.CreateMapper();
var csvConfig = new CsvConfiguration(CultureInfo.InvariantCulture)
{
Delimiter = "\t",
HeaderValidated = null,
MissingFieldFound = null,
MemberTypes = CsvHelper.Configuration.MemberTypes.Fields
};
using (var reader = new StringReader("BOLNumber\tProductID\tProductDescription\t\n1\t2\tMy Product"))
using (var csvr = new CsvReader(reader, csvConfig))
{
var bolDtos = csvr.GetRecords<BOLDto>().ToList();
var bols = _mapper.Map<IEnumerable<BOL>>(bolDtos);
}
}
public class BOLDto
{
[Name("BOLNumber")]
public int BOLNumber;
[Name("ProductID")]
public int ProductID;
[Name("ProductDescription")]
public string ProductDescription;
}
public class BOL
{
public int BOLNumber { get; set; }
public int ProductId { get; set; }
public string ProductDescription { get; set; }
}
I am fairly new to c# and would like to know how values can be called from a file instead of statically hard coding it in the class. I know in java spring boot applications we can have it in application.properties files. In my case I have the db hostname, username and pwd stored in a file
namespace NunitTestCase
{
[TestFixture]
public class Test
{
string query = "SELECT * FROM SYSTEM.ADMIN.EMPLOYEE";
string host = "vm1.test.app.com"; //want these data in a file
int port = 5480;
string dbName = "SYSTEM";
string userName = "admin";
string password = "password";
[Test]
public void TestCase()
{
var builder = new ConnectionStringBuilder();
builder.UserName = userName;
builder.Password = password;
builder.Port = port;
builder.Host = host;
builder.Database = dbName;
using (var con = new Connection(builder.ConnectionString))
{
con.Open();
NUnit.Framework.Assert.That(con.State == ConnectionState.Open);
using (var cmd = new Command(query, con))
{
var rdr = cmd.ExecuteReader();
while (rdr.Read())
{
for (int i = 0; i < rdr.FieldCount; i++)
{
object o = null;
try
{
o = rdr.GetValue(i);
}
catch (Exception ex)
{
o = ex.Message;
}
Console.WriteLine(o);
}
}
}
con.Close();
NUnit.Framework.Assert.That(con.State == ConnectionState.Closed);
}
}
}
}
file.yaml
database:
host: "vm1.test.app.com"
port: 5480
dbName: "SYSTEM"
userName: "admin"
password: "password"
How do I make changes in my code so that instead of hardcoding, these values can be picked up from the file
Traditionally, in .net we store configuration in .json/.xml files and C# supports built-in functionality to parse it, but as far as you are using .YAML file you can install the library to parse this file:
YAMLDotNet
and use this to parse.
public class Database {
public string Host { get; set; }
public string Port { get; set; }
public string DbName { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
}
public class Configuration
{
public Database Database { get; set; }
}
var yamlString = File.ReadAllText(#"...\file.yaml");
var deserializer = new DeserializerBuilder().WithNamingConvention(new CamelCaseNamingConvention()).Build();
var config = deserializer.Deserialize<Configuration>(yamlString);
If you don't want to use any libraries you can parse it manually, so create a class which reflects your model in YAML, something like:
Function to get the value of a property:
public string GetValueOfPropertyYaml(string yamlStr) {
return yamlStr?.Split(":")?.Skip(1)?.FirstOrDefault()?.Trim() ?? string.Empty;
}
Main code:
string[] yamlStringArray = File.ReadAllLines(#"..\file.yaml");
var config = new Database();
foreach (var yamlStr in yamlStringArray) {
if (yamlStr.Contains("host:")) {
config.Host = GetValueOfPropertyYaml(yamlStr);
}
if (yamlStr.Contains("port:"))
{
config.Port = GetValueOfPropertyYaml(yamlStr);
}
if (yamlStr.Contains("dbName:"))
{
config.DbName = GetValueOfPropertyYaml(yamlStr);
}
if (yamlStr.Contains("userName:"))
{
config.UserName = GetValueOfPropertyYaml(yamlStr);
}
if (yamlStr.Contains("password:"))
{
config.Password = GetValueOfPropertyYaml(yamlStr);
}
}
;
// use filled `config` variable below.
your model:
public class Database
{
public string Host { get; set; }
public string Port { get; set; }
public string DbName { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
}
NOTE: I highly recommend you to use library, because it was already tested and worked perfectly(my method should be tested properly)
I want to map a two tables in entity framework 6 and need some help! It is for my chat application; I need to map user conversations into the database. Both group and private messages. For this question however, if you help me with the private messaging mapping, I should hopefully work out the group by myself :) anyway....
Each user can talk to any other user. They however share the same data, which is where I am struggling a bit: how to set the keys to the exact same data without duplication. This is what I have so far:
**EDIT - new code *****
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
namespace CodeFirstNewDatabaseSample
{
static void Main(string[] args)
{
using(var db = new PrivateMessageContext())
{
Console.Write("Enter message: ");
var message = Console.ReadLine();
var userFrom = "userFrom";
var userTo = "userTo";
var messageDetail = new PrivateMessageDetail(MessageDate = DateTime.Now, FromUser = userFrom, message = message);
var pm = new PrivateMessageHeader { User1 = userFrom, User2 = userTo, TimeStamp = DateTime.Now };
pm.Messages.Add(messageDetail);
db.PrivateMessages.Add(pm);
db.SaveChanges();
// Display all Blogs from the database
foreach(var pmsg in db.PrivateMessages)
{
var query = pmsg;
Console.WriteLine(pmsg.Message);
}
Console.ReadKey();
}
}
}
public class PrivateMessage
{
public int PrivateMessageId { get; set; }
public string Message { get; set; }
public DateTime TimeStamp { get; set; }
// public int User1Id { get; set; }
public virtual string user1 { get; set; }
// public virtual User user1 { get; set; }
public virtual string user2 { get; set; }
//public int User1Id { get; set; }
// public virtual User user2 { get; set; }
}
public class User
{
public int UserId { get; set; }
public string UserName { get; set; }
}
public class PrivateMessageContext : DbContext
{
public DbSet<PrivateMessage> PrivateMessages { get; set; }
}
public class Send
{
/* void Send(userTo, userFrom, message)
{
using (var db = new PrivateMessageContext()) {
var query = from pm in db.PrivateMessages;
foreach(var msg in pm)
{
var user1 = msg.user1;
var user2 = msg.user2;
if ( (user1==userTo && user2==userFrom) || (user1==userFrom && user2==userTo))
{
msg.Message += message;
return;
}
else {
// pair doesn't exist
var PrivateMessage = new PrivateMessage { user1 = userFrom; user2 = userTo; TimeStamp = DateTime.Now; Message = message; };
db.PrivateMessages.Add(PrivateMessage);
db.SaveChanges();
}
}
}*/
}
}
I am now stuck on two things - how to make a callable class which checks if there is previous message history (the Send() ) and how to use the User username instead of strings...
Thank you
*update 3*
static void Main(string[] args)
{
using(var db = new PrivateMessageContext())
{
Console.Write("Enter message: ");
var message = Console.ReadLine();
var userFrom = "userFrom";
var userTo = "userTo";
var messageDetail = new PrivateMessageDetail(MessageDate = DateTime.Now, FromUser = userFrom, message = message);
var pm = new PrivateMessageHeader { User1 = userFrom, User2 = userTo, TimeStamp = DateTime.Now, Message = messageDetail };
db.PrivateMessages.Add(pm);
db.SaveChanges();
// Display all Blogs from the database
foreach(var pmsg in db.PrivateMessages)
{
var query = pmsg;
Console.WriteLine(pmsg.Message);
}
Console.ReadKey();
}
}
}
public class PrivateMessageContext : DbContext
{
public DbSet<PrivateMessageHeader> PrivateMessages { get; set; }
}
What you probably want is some kind of master/detail. What you would do is create a PrivateMessageHeader type, and this would contain the participants in the private message. Then you would have a PrivateMessageDetail type that would contain the actual messages. There would be a 1 to many association between Header and details.
So something like this:
public class PrivateMessageHeader {
public PrivateMessageHeader() { Messages = new List<PrivateMessageDetail>; }
public int PrivateMessageHeaderId {get;set;}
public DateTime ThreadTime {get;set;} // Date of the start of thread
public string User1 {get;set;}
public string User2 {get;set;} // this could be made to a list to allow multiples
public ICollection<PrivateMessageDetail> Messages {get;set;}
}
public class PrivateMessageDetail {
public int PrivateMessageDetailId {get;set;}
public DateTime MessageDate {get;set;}
public string FromUser {get;set;} // Don't need ToUser, it's already in header
public string Message {get;set;}
public PrivateMessageHeader parent {get;set;}
}
I maintain an API that, based on a request for a list of people, returns a different result set based on the request. For example, some API clients want to get a list of people and a list of their interactions, others want people and a list of their metadata. All this can be specified int he request to the API method that returns people.
This does not appear to work:
using (var dbcontext = new ExampleEntities())
{
var query = dbcontext.People.AsQueryable();
//determined in earlier application logic based on request
if(includeMetadata)
{
query = query.Include("metadata");
}
//determined in earlier application logic based on request
if(includeInteractions)
{
query = query.Include("interactions");
}
/* ...SNIP... */
}
What I don't want to do is this:
var query = dbcontext.People.Include("Metadata").Include("interactions");
which will mean every request to get a person will include ALL their related entities, even if the requesting API client does not need them.
I also don't want to code every possible combination of logic:
if(includeMetadata && includeInteractions)
{
var query = dbcontext.People.Include("Metadata").Include("interactions");
}
else if(includeMetadata)
{
var query = dbcontext.People.Include("Metadata");
}
else if(includeInteractions)
{
var query = dbcontext.People.Include("Interactions");
}
else
{
var query = dbcontext.People;
}
This will result in hard-to-maintain code, however, I realize I could code generate this if needed.
You can chain the IQueryable's
using (var dbcontext = new ExampleEntities())
{
var query = dbcontext.People.AsQueryable();
if(includeMetadata)
{
query = query.Include("metadata");
}
if(includeInteractions)
{
query = query.Include("interactions");
}
}
Your first example should work if you replace u with query
u = u.Include("metadata");
with
query = query.Include("metadata");
Works fine here... checking the sql statements with the EF 6 Log handler
[TestClass]
public void SomeTestClass
{
[TestMethod]
public void ShouldLoadOnlyRequiredCollections()
{
Database.SetInitializer(new DropCreateDatabaseAlways<HomesContext>());
var db = new HomesContext();
Assert.IsFalse(db.Homes.Any());
var home = db.Homes.Create();
db.Homes.Add(home);
home.Staff.Add(new Staff { Name = "wilma" });
home.Staff.Add(new Staff { Name = "betty" });
home.Residents.Add(new Resident { Name = "fred" });
home.Residents.Add(new Resident { Name = "barney" });
db.SaveChanges();
db = null;
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<HomesContext>());
var sb = new StringBuilder();
db = new HomesContext();
db.Database.Log = ((s) => { sb.Append(s + "\r"); });
Assert.IsTrue(db.Homes.Any());
string log;
log = sb.ToString();
Assert.IsTrue(sb.ToString().Contains("FROM [dbo].[Homes]"));
sb = new StringBuilder(); //ok get residents
var q = db.Homes.Include("Residents");
Assert.IsTrue(string.IsNullOrEmpty(sb.ToString()));
var lst = q.ToList();
log = sb.ToString();
Assert.IsTrue(sb.ToString().Contains("[dbo].[Homes]"));
Assert.IsTrue(sb.ToString().Contains("[dbo].[Residents]"));
Assert.IsTrue(!sb.ToString().Contains("[dbo].[Staff]"));
sb = new StringBuilder(); //get staff
q = db.Homes.Include("Staff");
Assert.IsTrue(string.IsNullOrEmpty(sb.ToString()));
lst = q.ToList();
log = sb.ToString();
Assert.IsTrue(log.Contains("[dbo].[Homes]"));
Assert.IsTrue(!log.Contains("[dbo].[Residents]"));
Assert.IsTrue(log.Contains("[dbo].[Staffs"));
sb = new StringBuilder(); //get residents and staff
q = db.Homes.Include("Staff");
q = q.Include("Residents");
lst = q.ToList();
log = sb.ToString();
Assert.IsTrue(log.Contains("[dbo].[Homes]"));
Assert.IsTrue(log.Contains("[dbo].[Residents]"));
Assert.IsTrue(log.Contains("[dbo].[Staffs]"));
}
}
public class HomesContext:DbContext
{
public DbSet<Home> Homes { get; set; }
}
public class Home
{
public Home()
{
Staff = new List<Staff>();
Residents = new List<Resident>();
}
public int HomeId { get; set; }
public string HomeName { get; set; }
public int MaxResidents { get; set; }
public int MaxStaff { get; set; }
public int CurrentResidents { get; set; }
[NotMapped]
public int CurrentStaff { get; set; }
public IList<Staff> Staff { get; set; }
public IList<Resident> Residents { get; set; }
}
public class Staff
{
public int StaffId { get; set; }
public string Name { get; set; }
public int HomeId { get; set; }
public Home Home { get; set; }
}
public class Resident
{
public int ResidentId { get; set; }
public string Name { get; set; }
public int HomeId { get; set; }
public Home Home { get; set; }
}
The program below is a socket program that receives data at a pretty fast pace. It runs fine with the CodeFirst section disabled. If I enable it, the program starts out fine but then degrades slowly to the point where nothing appears to be written to the SQL EXPRESS 2012 db. I check this by running the SQL statement below which just selects the last five rows n SQL Management Studio 2012.
Is there something that I am doing wrong?
select * from [MarketDataEntities]
where MarketDataEntities.MarketDataEntityID not in (
select top (
(select count(*) from [MarketDataEntities]) - 5
) MarketDataEntities.MarketDataEntityID
from [MarketDataEntities]
)
using (var dbTDC = new TickDataTestContext())
{
var tde = new SymbolTickDataEntity { Symbol = symbol };
if (!dbTDC.SymbolTickDataDbSet.Any(a => a.Symbol.Equals(symbol)))
{
dbTDC.SymbolTickDataDbSet.Add(tde);
dbTDC.SaveChanges();
}
var mdde = new MarketDataDepthEntity();
dbTDC.MarketDataDepthDbSet.Add(mdde);
dbTDC.SaveChanges();
while (true)
{
// Wait for next request from client
int len = socket.Receive(zmq_buffer);
if (len < 1)
{
Console.WriteLine("Len < 1");
continue;
}
//Console.WriteLine("Got quote");
count++;
// Copy the bytes
byte[] bytes = new byte[len];
Buffer.BlockCopy(zmq_buffer, 0, bytes, 0, len);
MarketDataDepth mdd = MarketDataDepth.CreateBuilder().MergeFrom(bytes).Build();
PrintMarketDataDepth(mdd);
#if false
for (int i = 0; i < mdd.MdCount; i++)
{
MarketData md = mdd.MdList[i];
string timestamp = md.Time;
int index = timestamp.IndexOf(",");
if(-1 != index)
timestamp = timestamp.Remove(index);
DateTime parseResult;
if (false == System.DateTime.TryParseExact(timestamp, format, provider, DateTimeStyles.None, out parseResult))
continue;
var mde = new MarketDataEntity
{
NMDDTag = (long)mdd.NMDDTag,
QType = (0 == md.QuoteType ? QuoteType.Bid : QuoteType.Ask),
QPrice = md.Price,
QSize = md.Size,
QSource = md.Source,
QLiquidityTag = md.ID,
QSilo = md.Silo,
QTimeStamp = parseResult
};
dbTDC.MarketDataDbSet.Add(mde);
mdde.Depth.Add(mde);
}
if (0 == count % 500)
dbTDC.SaveChanges();
#endif
}
}
}
catch (DbEntityValidationException e)
{
foreach (var eve in e.EntityValidationErrors)
{
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
throw;
}
}
}
public enum QuoteType { Bid = 0, Ask }
public class MarketDataEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int MarketDataEntityID { get; set; }
public long NMDDTag { get; set; }
public QuoteType QType { get; set; }
public double QPrice { get; set; }
public double QSize { get; set; }
public string QSource { get; set; }
public string QLiquidityTag { get; set; }
public string QSilo { get; set;}
[Column("timestamp", TypeName = "datetime2")]
public DateTime QTimeStamp { get; set; }
}
public class MarketDataDepthEntity
{
public int MarketDataDepthEntityID { get; set; }
public virtual IList<MarketDataEntity> Depth { get; set; }
[Column("timestamp", TypeName = "datetime2")]
public DateTime TimeStamp { get; set; }
public MarketDataDepthEntity() { Depth = new List<MarketDataEntity>(); }
}
public class SymbolTickDataEntity
{
public int SymbolTickDataEntityID { get; set; }
[Key]
[Required]
public string Symbol { get; set; }
public virtual IList<MarketDataDepthEntity> Mdds { get; set; }
public SymbolTickDataEntity() { Mdds = new List<MarketDataDepthEntity>(); }
}
public class TickDataTestContext : DbContext
{
public DbSet<MarketDataEntity> MarketDataDbSet { get; set; }
public DbSet<MarketDataDepthEntity> MarketDataDepthDbSet { get; set; }
public DbSet<SymbolTickDataEntity> SymbolTickDataDbSet { get; set; }
}
From your code looks like you are keeping around the TickDataTestContext for the lifetime of your application. So as you keep adding data the local cache keeps increasing increasing memory usage hence performance degradation.
You should rewrite the code to create a new instance of TickDataTestContext for each request that needs to be saved then do the work, save changes and dispose the context.