Combining data from 2 databases in MVC - c#

I am fairly new to asp.net mvc and I currently have an application that shows a number of errors. I have 2 pages that contain Application Errors and Log Errors. The data comes from 2 different databases but I am wanting to display the data from both databases on one page.
The tables have headings with different names that mean the same thing e.g. ApplicationName in the Application Database is the same thing as LogName in the Log Database.
Below is a small example of what I currently have and an example of what I am wanting.
Current
Application Errors
ID ApplicationName ApplicationMessage ApplicationDate
1 Something Hello World 01/01/2015
2 Something Else Another Message 03/01/2015
Log Errors
ID LogName LogMessage LogDate
1 Some Log A log message 02/01/2015
2 Another Log Another Log Message 04/01/2015
What I Want
Internal Errors
ID Name Message Date
1 Something Hello World 01/01/2015
2 Some Log A log message 02/01/2015
3 Something Else Another Message 03/01/2015
4 Another Log Another Log Message 04/01/2015
At the minute, I have 2 separate models for each database but I think I need to merge both models into one model that combines them both but I am unsure on how to do this. How would I be able to merge both data sources together to display the data within the same page?
Current Models
Application
[Table("ELMAH_Error")]
public class ElmahError
{
[Key]
public System.Guid ErrorId { get; set; }
public System.String Application { get; set; }
public System.String Host { get; set; }
public System.String Type { get; set; }
public System.String Source { get; set; }
public System.String Message { get; set; }
public System.String User { get; set; }
public System.Int32 StatusCode { get; set; }
public System.DateTime TimeUtc { get; set; }
public System.Int32 Sequence { get; set; }
public System.String AllXml { get; set; }
}
Log
[Table("LogEntry")]
public class LogEntry
{
[Key]
public Int64 ID { get; set; }
public DateTime LogDate { get; set; }
public Int16 Priority { get; set; }
public string SourceClass { get; set; }
public string Category { get; set; }
public string Message { get; set; }
public string UserID { get; set; }
public string ProcessID { get; set; }
}
From the models, there are a number of fields that I would like to merge as well as fields that are not similar that I would also like to include. The model below shows exactly what I want but I just don't know how to implement it.
Internal Errors
public class InternalErrors
{
public string Id { get; set; } //L:ID && E:ErrorId
public int Priority { get; set; } //L:Priority
public string Application { get; set; } //L:SourceClass && E:Application
public string Message { get; set; } //L:Message && E:Message
public string Type { get; set; } //L:Category && E:Type
public string User { get; set; } //L:UserID && E:User
public string ProcessID { get; set; } //L:ProcessID
public DateTime Date { get; set; } //L:LogDate && E:TimeUtc
public int StatusCode { get; set; } //E:StatusCode
public string AllXml { get; set; } //E:AllXml
public int Sequence { get; set; } //E:Sequence
public int ErrorCount { get; set; } //E:ErrorCount
}
I hope this is enough information for you to provide an answer, if you need anything else, let me know.
Thanks in advance

if what you want is this
Internal Errors
ID Name Message Date
1 Something Hello World 01/01/2015
2 Some Log A log message 02/01/2015
3 Something Else Another Message 03/01/2015
4 Another Log Another Log Message 04/01/2015
then create a class with name InternalErrors as follows.
public class InternalErrors
{
public int ID;
public string Name;
public string Message;
public DateTime Date;
}
Now you can write a Linq Query as follows to get data from Application Errors and Log Errors and Perform union on it.
var AppErrors=from AE in _db.ApplicationErrors select AE;
var LogErrors=from LE in _dc.LogErrors select LE;
var internerrors=AppErrors.Union(LogErrors);
var InternalErrors=(from ie in internerrors select new InternalErrors()
{
ID=ie.ID,
Message=ie.ApplicationMessage,
Name=ie.ApplicationName,
Date=ie.ApplicationDate
}).ToList();

The viewmodel approach from MRebati is the best solution.
I often find it usefull to have a base class and different implementations:
public abstract class ErrorViewModel
{
public abstract int Id { get; }
public abstract string Name { get; }
}
public class ElmahErrorViewModel
{
public ElmahErrorViewModel(ElmahError instance)
{
this.Instance = instance;
}
public ElmahError Instance { get; private set; }
public int Id { get { return Instance.ErrorId; } }
public string Name { get { return instance.Appication; } }
}
that way you can create a List<ErrorViewModel> and add entries with
var items = from e in context.ElmahErrors
select new ElmahErrorViewModel(e);
list.AddRange(items);
var items2 = from l in context.LogEntrys
select new LogEntryViewModel(l);
list.AddRange(items2);
This is very usefull since you hide the details but you still can seprate the list and access the underlying object with
var elmahErrors = items.OfType<ElmahErrorViewModel>().Select(x => x.Instance);

There are many ways to provide data from the models to the View.
One is the ViewModel. It must contain the data you want to send to view. Look at this:
using System;
public class ErrorViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Message { get; set; }
public DateTime Date { get; set; }
}
And in the Controller you need to Create a list of this ViewModel and populate it with your data.

you can use linq
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var elmahErrorList = new List<ElmahError>{
new ElmahError{ ErrorId = Guid.NewGuid(), Application = "Something",Message = "Hello World" , TimeUtc = DateTime.Now },
new ElmahError{ ErrorId = Guid.NewGuid(), Application = "Something Else",Message = "Another Message" , TimeUtc = DateTime.Now }
};
var logEntryList = new List<LogEntry>{
new LogEntry{ ID = 1, SourceClass = "Something",Message = "Hello World" , LogDate = DateTime.Now },
new LogEntry{ ID = 1, SourceClass = "Something Else",Message = "Another Message" , LogDate = DateTime.Now }
};
var internalErrorsList = new List<InternalErrors>();
var elmahErrorListinternalErrorses = elmahErrorList.Select(e => new InternalErrors
{
Id = e.ErrorId.ToString(),
Application = e.Application,
Message = e.Message,
Type = e.Type,
User = e.User,
Date = e.TimeUtc,
StatusCode = e.StatusCode,
AllXml = e.AllXml,
Sequence = e.Sequence
});
internalErrorsList.AddRange(elmahErrorListinternalErrorses);
var elmahErrorListlogEntryLists = logEntryList.Select(l => new InternalErrors
{
Id = l.ID.ToString(),
Priority = l.Priority,
Application = l.SourceClass,
Message = l.Message,
Type = l.Category,
User = l.UserID,
Date = l.LogDate
});
internalErrorsList.AddRange(elmahErrorListlogEntryLists);
internalErrorsList.ForEach(f =>
{
Console.Write(f.Id); Console.Write("\t");
Console.Write(f.Application);Console.Write("\t");
Console.Write(f.Message);Console.Write("\t");
Console.Write(f.Date);Console.Write("\t");
Console.WriteLine();
});
}
public class InternalErrors
{
public string Id { get; set; } //L:ID && E:ErrorId
public int Priority { get; set; } //L:Priority
public string Application { get; set; } //L:SourceClass && E:Application
public string Message { get; set; } //L:Message && E:Message
public string Type { get; set; } //L:Category && E:Type
public string User { get; set; } //L:UserID && E:User
public string ProcessID { get; set; } //L:ProcessID
public DateTime Date { get; set; } //L:LogDate && E:TimeUtc
public int StatusCode { get; set; } //E:StatusCode
public string AllXml { get; set; } //E:AllXml
public int Sequence { get; set; } //E:Sequence
public int ErrorCount { get; set; } //E:ErrorCount
}
public class ElmahError
{
public System.Guid ErrorId { get; set; }
public System.String Application { get; set; }
public System.String Host { get; set; }
public System.String Type { get; set; }
public System.String Source { get; set; }
public System.String Message { get; set; }
public System.String User { get; set; }
public System.Int32 StatusCode { get; set; }
public System.DateTime TimeUtc { get; set; }
public System.Int32 Sequence { get; set; }
public System.String AllXml { get; set; }
}
public class LogEntry
{
public Int64 ID { get; set; }
public DateTime LogDate { get; set; }
public Int16 Priority { get; set; }
public string SourceClass { get; set; }
public string Category { get; set; }
public string Message { get; set; }
public string UserID { get; set; }
public string ProcessID { get; set; }
}
}
Demo : https://dotnetfiddle.net/mrWGDn

Related

Loop through 4 object lists & add their data in a ListView C# Xamarin.Forms

I am working on a Xamarin.Forms Project and I am at a dead-end of sorts. My issue is that I want to display user transactions which I pull from a server, in a listview, however I need four different pull requests to get all the data which means I have four different objects lists which I grouped by the transaction number as you can see in this screenshot:
The key transaction number can be seen and if you expand you'll see the other data within each transaction
Here is the code where I group the deserialised json lists with the common key:
var t = JsonConvert.DeserializeObject<List<trans_mod>>(transactions);
var l = JsonConvert.DeserializeObject<List<loc_mod>>(loc);
var d = JsonConvert.DeserializeObject<List<disc_mod>>(disc);
var it = JsonConvert.DeserializeObject<List<item_mod>>(itm);
var q = it.AsQueryable().GroupBy(g => g.trans).ToList();
var q2= d.AsQueryable().GroupBy(g => g.trans).ToList();
var q3 = l.AsQueryable().GroupBy(g => g.trans).ToList();
var q4 = t.AsQueryable().GroupBy(g => g.position).ToList();
Object Models for each list
public class loc_mod
{
[DataMember]
public string location { get; set; }
[JsonProperty(PropertyName = "#modify_stamp")]
public string stamp { get; set; }
[JsonProperty(PropertyName = "$trans")]
public string trans { get; set; }
}
public class disc_mod
{
[DataMember]
public string discount { get; set; }
[JsonProperty(PropertyName = "#modify_stamp")]
public string stamp { get; set; }
[JsonProperty(PropertyName = "$trans")]
public string trans { get; set; }
}
public class item_mod
{
[JsonProperty(PropertyName = "item.price")]
public string price { get; set; }
[JsonProperty(PropertyName = "item.name")]
public string name { get; set; }
[JsonProperty(PropertyName = "#modify_stamp")]
public string stamp { get; set; }
[JsonProperty(PropertyName = "$trans")]
public string trans { get; set; }
}
public class trans_mod
{
[DataMember]
public string refer { get; set; }
[DataMember]
public string date { get; set; }
[DataMember]
public string time { get; set; }
[DataMember]
public int points { get; set; }
[DataMember]
public string _total { get; set; }
[JsonProperty(PropertyName = "$$position")]
public string position { get; set; }
[JsonProperty(PropertyName = "#modify_stamp")]
public string stamp { get; set; }
[JsonProperty(PropertyName = "$trans")]
public string trans { get; set; }
}
public class itms
{
public string price { get; set; }
public string name { get; set; }
public DateTime stamp { get; set; }
[JsonProperty(PropertyName = "$trans")]
public string trans { get; set; }
}
What I want to do is to loop through all four lists and add the data from each list in the listview but I can't think of a way I can do that.
Listview Add() code Example:
Transactions.Add(new Transaction
{
Details = "Date: " + ti[i].date + " | Time: " + ti[i].time + " |
Reference: " + ti[i].refer,
Isvisible = false, Items= ti[i].item, Total = ti[i].total, Discount
= ti[i].discount
});
Sorry if this is a bit confusing, it's confusing for me as well as I am a relative beginner. Any help is welcome!
Define an Interface that your item classes all implement.
That interface has a method that returns whatever you need for listview.
public Interface IHasTransaction
{
Transaction GetTransaction();
}
public class loc_mod : IHasTransaction
{
...
public Transaction GetTransaction()
{
// Use fields of this class to create a Transaction.
return new Transaction(...);
}
}
public class disc_mod : IHasTransaction
{
...
}
If you want, you can make a list that has a mixture of these:
public List<IHasTransaction> models = new List<IHasTransaction>();
models.Add(new loc_mod(...));
models.Add(new disc_mod(...));
Given any of these items
IHasTransaction model
You can easily get the corresponding Transaction:
model.GetTransaction()
OR
var lm = new loc_mod(...);
lm.GetTransaction()

How to fix Error while converting Json string to Object C#?

Im using C# to get a file from my local pc data folder.
This is the code to do that:
var _rootpath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + directory;
var ENC = new Encryption();
var s = File.ReadAllText(_rootpath + "json");
var x = ENC.RijndaelDecrypt(s, App.EncryptionPassword);
This works fine so far.
x got now this value (so this is the string I want to convert to an object) :
{
"items":[
{
"id":194,
"guid":"594394",
"name":"Test",
"connectorId":248,
"customerId":1,
"customerName":"company",
"connectorTypeId":10,
"connectorTypeIcon":null,
"connectorCategoryId":1,
"vendor":"FasterForward",
"isActive":true,
"shopId":null,
"sku":null,
"workerBearerToken":"",
"workerUri":"http://localhost:9000"
}
],
"responseStatus":null
}
After this I want to convert this to an object
var _response = JsonConvert.DeserializeObject<CrmJobListResponse>(x);
This line gives an error:
{"Error converting value x to type 'ServiceModel.CrmJobListResponse'. Path '', line 1, position 991."}
ServiceModel.CrmJobListResponse:
namespace ServiceModel
{
public class CrmJobListResponse : ResponseBase
{
public CrmJobListResponse();
public List<CrmJob> Items { get; set; }
}
}
CrmJob class:
namespace ServiceModel.DTO
{
public class CrmJob : IHasId<int>
{
public CrmJob();
[Ignore]
public string WorkerBearerToken { get; set; }
[PropertyValue("sku")]
public string SKU { get; set; }
[PropertyValue("shop_id")]
public string ShopId { get; set; }
public bool IsActive { get; set; }
public string Vendor { get; set; }
public int ConnectorCategoryId { get; set; }
[Ignore]
public string WorkerRefreshToken { get; set; }
public string ConnectorTypeIcon { get; set; }
public string CustomerName { get; set; }
public int CustomerId { get; set; }
public int ConnectorId { get; set; }
[PropertyValue("jobname")]
public string Name { get; set; }
public string Guid { get; set; }
public int Id { get; set; }
public int ConnectorTypeId { get; set; }
[Ignore]
public string WorkerUri { get; set; }
}
}
Does anyone know why it can't convert my Json string to an object?
I didn't made the code myself, but I don't see why It should go wrong...
If you have a hard time creating DTOs you have some tools that may assist you https://app.quicktype.io/
You can also use paste special in VS to paste a Json directy to a C# class.
This also shows you if you malformed a Json.

How do I sort my list of type class?

I have a class that looks like this
class FeaturedListing
{
public string Title { get; set; }
public string Link { get; set; }
public string Published { get; set; }
public string Views { get; set; }
public string Featured { get; set; }
public string CategoryName { get; set; }
}
And then I have a list that looks like this
public static List<FeaturedListing> FeatiredListingsList = new List<FeaturedListing>();
After adding a few objects to that list, how do I properly sort by Views
views looks like this
0 visits
52 visits
5 visits
etc.
Simplest way is to do an OrderBy on your FeaturedListing.Views.
var orderedList = FeatiredListingsList.OrderBy(x => x.Views).ToList();
However, if you're at liberty to change the structure of your program, you should really consider making Views an int so you can do proper numerical sorting. If you must, for some reason, output the value of Views as 0 visits, 52 visits etc, a better approach is to create a get only property in your FeaturedListing class like this:
public class FeaturedListing
{
public string Title { get; set; }
public string Link { get; set; }
public string Published { get; set; }
public int Views { get; set; }
public string ViewsStr { get { return string.Format("{0} visits", Views); } }
public string Featured { get; set; }
public string CategoryName { get; set; }
}
Use the List.Sort - Sorts the elements in the entire List using the specified System.Comparison..
void Main()
{
var reatiredListingsList = new List<FeaturedListing>();
reatiredListingsList.Add(new FeaturedListing{ Views = "0 Views"});
reatiredListingsList.Add(new FeaturedListing{ Views = "52 Views"});
reatiredListingsList.Add(new FeaturedListing{ Views = "5 Views"});
reatiredListingsList.Sort((x, y) => {
var xv = int.Parse(x.Views.Replace(" Views", ""));
var yv = int.Parse(y.Views.Replace(" Views", ""));
return xv < yv ? -1 : (xv > yv ? 1 : 0);
});
}
class FeaturedListing
{
public string Title { get; set; }
public string Link { get; set; }
public string Published { get; set; }
public string Views { get; set; }
public string Featured { get; set; }
public string CategoryName { get; set; }
}

Getting error when loading data from db to class object

i have a class customer. in which i am trying to load data from the access db database.
Customer class structure is below:
public class Customer
{
public int CustomerId { get; set; }
public string CustomerName { get; set; }
public string CustAddress { get; set; }
public string PnoneNo { get; set; }
public string MobileNo { get; set; }
public string CstNo { get; set; }
public string DlNo { get; set; }
public decimal BalAmt { get; set; }
}
and my table structure in db is as below:
now when i am trying to load data in customer class it is throwing an error:
"Specified cast is not valid."
for loading data in to class i am using below code:
public static List<Customer> LoadListItems(string strTable, string strOrderBy)
{
List<Customer> lstCustomer=null;
try
{
DataUtility objDataUtility = new DataUtility();
DataTable objCustomerList = objDataUtility.LoadCustomerInfo(strTable, strOrderBy);
lstCustomer= objCustomerList.AsEnumerable().Select(row =>
new Customer
{
CustomerId = row.Field<int>("CID"), //throwing error for this line
CustomerName = row.Field<string>("salPNm"),
CustAddress = row.Field<string>("cadd"),
MobileNo = row.Field<string>("cmbl"),
PnoneNo = row.Field<string>("cph"),
DlNo = row.Field<string>("cDlN"),
CstNo = row.Field<string>("cTin"),
BalAmt = row.Field<decimal>("cobal")
}).ToList();
}
catch (Exception ex)
{
throw ex;
}
return lstCustomer;
}
In above method CustomerId = row.Field<int>("CID"), is throwing an error coz when i commented this line it is working fine.
Please help me how can i get the int values from iennumrable list.
Thanks in Advance.
Eshwer
Replace it with -
CustomerId = Convert.ToInt64(row.Field<int>("CID"));
Also, check the value by applying Quick Watch over this line - row.Field<int>("CID"). See if it's not null and what's the value its returning.
Try this
public class Customer
{
public Int64 CustomerId { get; set; }
public string CustomerName { get; set; }
public string CustAddress { get; set; }
public string PnoneNo { get; set; }
public string MobileNo { get; set; }
public string CstNo { get; set; }
public string DlNo { get; set; }
public decimal BalAmt { get; set; }
}
and
CustomerId = row.Field<Int64>("CID")
I think that your identity is a long integer.

Why can't I send my custom class through my webservice?

I have these classes:
public abstract class CustomField
{
public String Id { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public FieldType Type { get; set; }
public enum FieldType
{
String = 0,
Integer = 1,
Boolean = 2,
List = 3
}
}
public class StringCustomField:CustomField
{
public String Value { get; set; }
public Int32 MinLenght { get; set; }
public Int32 MaxLenght { get; set; }
public StringCustomField()
{
this.Type = FieldType.String;
}
}
public class CustomGroup
{
public String Id { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public List<CustomField> FieldList = new List<CustomField>();
}
When I try to transfer CustomGroup through my webservice I get this error:
The remote server returned an error: NotFound
Serialization is failing when C# tries to transfer my StringField through my CustomField.
What am I doing wrong?
Marc Gravel tell me to do that and i understand the solution but some thing is wrong, no effects, cath the same error!! , help!!
[XmlInclude(typeof(StringCustomField))]
[XmlInclude(typeof(IntegerCustomField))]
[XmlInclude(typeof(BooleanCustomField))]
[XmlInclude(typeof(ListCustomField))]
public abstract class CustomField
{
public String Id { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public FieldType Type { get; set; }
public enum FieldType
{
String = 0,
Integer = 1,
Boolean = 2,
List = 3
}
}
If you are sending subclasses as xml, you will need [XmlInclude]:
[XmlInclude(typeof(StringCustomField))]
public abstract class CustomField
{...}
You can add multiple [XmlInclude(...)] markers for any other subclasses in the model.
List<CustomField> will serialize and deserialize to a CustomField[] if you're using a web service, won't it?
use
public class CustomGroup
{
public String Id { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public List<CustomField> FieldList = new List< StringCustomField >();
}
instead
If i understand you correctly, you should
1. connect your web service to your app
2. use the namespace of the WS, so all the classes will be used from the Proxy
i don't think that the local class will be understood by the remote web serivce correctly, even if you're using the same assembly on both parties

Categories

Resources