Filtering mongodb data - c#

I have the following model:
Base class:
public abstract class Identifiable{
private ObjectId id;
private string name;
protected Identifiable(){
id = ObjectId.GenerateNewId();
}
[BsonId]
public ObjectId Id{
get { return id; }
set { id = value; }
}
[BsonRequired]
public string Name{
get { return name; }
set { name = value; }
}
}
The name is unique.
A channel class
public class Channel : Identifiable{
private DateTime creationDate;
private string url;
private DailyPrograming dailyPrograming;
public DailyPrograming DailyPrograming{
get { return dailyPrograming; }
set { dailyPrograming = value; }
}
public DateTime CreationDate{
get { return creationDate; }
set { creationDate = value; }
}
public string Url{
get { return url; }
set { url = value; }
}
}
Daily programs. The name property is the date stored as ddMMyyyy:
public class DailyPrograming : Identifiable{
public DailyPrograming(){
DailyPrograms = new List<Program>(30);
}
public IList<Program> DailyPrograms { get; set; }
}
The programs:
public class Program : Identifiable{
private DateTime programDate;
private string category;
private string description;
public DateTime ProgramDate{
get { return programDate; }
set { programDate = value; }
}
public string Category{
get { return category; }
set { category = value; }
}
public string Description{
get { return description; }
set { description = value; }
}
}
Now, I want to filter the program of certain channel for specific date using:
public DailyPrograming GetProgramsForDate(string channelId, string prgDate){
ObjectId id = new ObjectId(channelId);
IMongoQuery query = Query.And(Query<Channel>.EQ(c => c.Id, id),
Query<DailyPrograming>.EQ(dp => dp.Name, prgDate));
var result = Database.GetCollection<DailyPrograming>(CollectionName).Find(query).FirstOrDefault();
return result;
}
But it never returns the existing data. How to retrieve the programings of a channel for a date?
-

var builder = Builders<BsonDocument>.Filter;
var filt = builder.Eq("Price", "9.20")
& builder.Eq("ProductName", "WH-208");
var list = await collection.Find(filt).ToListAsync();
We can use & instead of $and. See this post, for another example.

According to your sample I used id = "54c00c65c215161c7ce2a77c" and prgDate = "2212015"
then I changed the query to this:
var collection = database.GetCollection<Channel>("test6");
var id = new ObjectId("54c00c65c215161c7ce2a77c");
var query = Query.And(Query<Channel>.EQ(c => c.Id, id), Query<Channel>.EQ(c => c.DailyPrograming.Name, "2212015"));
var result = collection.Find(query).FirstOrDefault();
this query works fine
Some point:
Your collection type is Chanel not DailyPrograming
When your collection is Chanel you have to use Query<Channel> and query nested DailyPrograming via Query<Channel>.EQ(c => c.DailyPrograming.Name, "2212015")

Related

CsvHelper Looking for Non-existent Columns

The propblem: There is no "Name" field in the object or csv file, yet CsVHelper keeps looking for "Name" in the header. So why is it tripping there and what are some fixes?
When trying to build objects from a csv file, the following error comes up:
CsvHelper.HeaderValidationException: Header with name 'Name' was not found. If you are expecting some headers to be missing and want to ignore this validation, set the configuration HeaderValidated to null. You can also change the functionality to do something else, like logging the issue.
at CsvHelper.Configuration.ConfigurationFunctions.HeaderValidated(Boolean isValid, String[] headerNames, Int32 headerNameIndex, ReadingContext context)
I have tried setting HeaderValidated to null, but got the same results.
The header of the csv:
Id|Title|Description|AssignedToUserId|SourceUserId|DateCreated|DateAssigned|DateCompleted|Notes
The parsing code:
private static IEnumerable<T> GetCSVData<T>(string fullFileName)
{
PrintMembers<T>();
using (var reader = new StreamReader(fullFileName))
{
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
csv.Configuration.HasHeaderRecord = true;
csv.Configuration.IncludePrivateMembers = false;
csv.Parser.Configuration.Delimiter = "|";
var records = csv.GetRecords<T>().ToList();
return records;
}
}
}
A quick function for listing the public properties and fields of the class (T) being passed in outputs the following:
Properties...
Id
AssignedToUserId
SourceUserId
Title
Description
AssignedTo
Source
DateCreated
DateAssigned
DateCompleted
RelatedTasks
Notes
Fields...
[None]
They all have getters and setters.
EDIT
The IntermediateTask is the generic being fed into GetCSVData(). It has a default constructor. IntermediateTask is internal, but is in the same assembly as GetCSVData().
Code for the class(es) in question:
internal class IntermediateTask : Task
{
private int _Id;
new public int Id
{
get { return _Id; }
set { _Id = value; }
}
private int _AssignedToUserId;
public int AssignedToUserId
{
get { return _AssignedToUserId; }
set
{
_AssignedToUserId = value;
base.AssignedTo = userManager.Get(_AssignedToUserId);
}
}
private int _SourceUserId;
public int SourceUserId
{
get { return _SourceUserId; }
set
{
this._SourceUserId = value;
base.Source = userManager.Get(_SourceUserId);
}
}
public IntermediateTask() : base("", "", new IntermediateUser(), new IntermediateUser())
{
}
}
public class Task
{
public Task(string title, string description, User assignedTo, User source, DateTime? dateCreated = null, int id = 0)
{
this.RelatedTasks = new List<Task>();
this.Title = title;
this.Description = description;
this.AssignedTo = assignedTo;
this.Source = source;
this.DateCreated = dateCreated ?? DateTime.Now;
this.Id = id;
}
private int _Id;
public int Id
{
get { return _Id; }
protected set { _Id = value; }
}
public string Title { get; set; }
public string Description { get; set; }
public User AssignedTo { get; set; }
public User Source { get; set; }
public DateTime DateCreated { get; set; }
public DateTime? DateAssigned { get; set; }
public DateTime? DateCompleted { get; set; }
public IList<Task> RelatedTasks { get; set; }
public string Notes { get; set; }
override public string ToString()
{
return $"Id: {Id}; Title: {Title}";
}
}
In my case it complained about AssignedTo missing, but that is actually a property in the class that is not in the csv, so I had to add these two lines to make it work:
csv.Configuration.HeaderValidated = null;
csv.Configuration.MissingFieldFound = null;
I don't know why it would come up with 'Name' unless you have something different.

Neo4jClient Node/Relationship Class conventions

Is there a standard naming convention for the properties/methods of a node/relationship class when working with Neo4jClient?
I'm following this link Neo4jClient - Retrieving relationship from Cypher query to create my relationship class
However, there are certain properties of my relationship which i can't get any value despite the relationship having it. While debugging my code, i realized certain properties was not retrieved from the relationship when creating the relationship object.
this is my relationship class
public class Creates
{
private string _raw;
private int _sourcePort;
private string _image;
private int _DestinationPort;
private int _eventcode;
private string _name;
private string _src_ip;
private int _src_port;
private string _dvc;
private int _signature_ID;
private string _dest_ip;
private string _computer;
private string _sourceType;
private int _recordID;
private int _processID;
private DateTime _time;
private int _dest_port;
public string Raw { get { return _raw; } set { _raw = value; } }
public int SourcePort { get { return _sourcePort; } set { _sourcePort = value; } }
public string Image { get { return _image; } set { _image = value; } }
public int DestinationPort { get { return _DestinationPort; } set { _DestinationPort = value; } }
public int Eventcode { get { return _eventcode; } set { _eventcode = value; } }
public string Name { get { return _name; } set { _name = value; } }
public string Src_ip { get { return _src_ip; } set { _src_ip = value; } }
public int Src_port { get { return _src_port; } set { _src_port = value; } }
public string DVC { get { return _dvc; } set { _dvc = value; } }
public int Signature_ID { get { return _signature_ID; } set { _signature_ID = value; } }
public string Dest_ip { get { return _dest_ip; } set { _dest_ip = value; } }
public string Computer { get { return _computer; } set { _computer = value; } }
public string SourceType { get { return _sourceType; } set { _sourceType = value; } }
public int RecordID { get { return _recordID; } set { _recordID = value; } }
public int ProcessID { get { return _processID; } set { _processID = value; } }
public DateTime Indextime { get { return _time; } set { _time = value; } }
public int Dest_port { get { return _dest_port; } set { _dest_port = value; } }
}
This is another class
public class ProcessConnectedIP
{
public Neo4jClient.RelationshipInstance<Pivot> bindto { get; set; }
public Neo4jClient.Node<LogEvent> bindip { get; set; }
public Neo4jClient.RelationshipInstance<Pivot> connectto { get; set; }
public Neo4jClient.Node<LogEvent> connectip { get; set; }
}
This is my neo4jclient query to get the relationship object
public IEnumerable<ProcessConnectedIP> GetConnectedIPs(string nodeName)
{
try
{
var result =
this.client.Cypher.Match("(sourceNode:Process{name:{nameParam}})-[b:Bind_IP]->(bind:IP_Address)-[c:Connect_IP]->(connect:IP_Address)")
.WithParam("nameParam", nodeName)
.Where("b.dest_ip = c.dest_ip")
.AndWhere("c.Image=~{imageParam}")
.WithParam("imageParam", $".*" + nodeName + ".*")
.Return((b, bind, c, connect) => new ProcessConnectedIP
{
bindto = b.As<RelationshipInstance<Creates>>(),
bindip = bind.As<Node<LogEvent>>(),
connectto = c.As<RelationshipInstance<Creates>>(),
connectip = connect.As<Node<LogEvent>>()
})
.Results;
return result;
}catch(Exception ex)
{
Console.WriteLine("GetConnectedIPs: Error Msg: " + ex.Message);
return null;
}
}
This is the method to read the results
public void MyMethod(string name)
{
IEnumerable<ProcessConnectedIP> result = clientDAL.GetConnectedIPs(name);
if(result != null)
{
var results = result.ToList();
Console.WriteLine(results.Count());
foreach (ProcessConnectedIP item in results)
{
Console.WriteLine(item.Data.Src_ip);
Console.WriteLine(item.bindto.StartNodeReference.Id);
Console.WriteLine(item.bindto.EndNodeReference.Id);
Console.WriteLine(item.connectto.StartNodeReference.Id);
Console.WriteLine(item.connectto.EndNodeReference.Id);
Node<LogEvent> ans = item.bindip;
LogEvent log = ans.Data;
Console.WriteLine(log.Name);
Node<LogEvent> ans1 = item.connectip;
LogEvent log1 = ans1.Data;
Console.WriteLine(log1.Name);
}
}
}
Somehow, i'm only able to populate the relationship object with src_ip/src_port/dest_ip/dest_port values. the rest are empty.
Is there any possible reason why? I've played with upper/lower cases on the properties names but it does not seem to work.
This is the section of the graph im working with
This is the relationship properties sample:
_raw: Some XML dataSourcePort: 49767Image: C:\Windows\explorer.exeDestinationPort: 443EventCode: 3Name: Bind
IPsrc_ip: 172.10.10.104dvc: COMPUTER-NAMEsrc_port:
49767signature_id: 3dest_ip: 172.10.10.11Computer:
COMPUTRE-NAME_sourcetype:
XmlWinEventLog:Microsoft-Windows-Sysmon/OperationalRecordID:
13405621ProcessId: 7184_time: 2017-08-28T15:15:39+08:00dest_port: 443
I'm not entirely sure how your Creates class is ever populated, in particular those fields - as your Src_port property doesn't match the src_port in the sample you provided (case wise).
I think it's probably best to go back to a super simple version. Neo4jClient will map your properties to the properties in the Relationship as long as they have the same name (and it is case-sensitive).
So start with a new Creates class (and use auto properties - it'll make your life a lot easier!)
public class Creates
{
public string Computer { get; set; }
}
Run your query with that and see if you get a result, then keep on adding properties that match the name and type you expect to get back (int, string etc)
It seems that i have to give neo4j node/relationship property names in lowercase and without special characters at the start of the property name, in order for the above codes to work.
The graph was not created by me at the start thus i had to work on it with what was given. I had to get the developer who created the graph to create the nodes with lowercases in order for the above to work.

c# how to give constructor fields from another class

I have 3 Classes : Masina (Car), Destinatie (Destination) and MasinaDestinatie (CarDestination).
I need the third class to get the values of the car number _nr_masina and the destination _cod_dest through it's own constructor.
I need to make a constructor with parameters in the third class that stores the values of _nr_masina and _cod_dest.
Anyone know how can i do this exactly? I've tried making the private fields public and putting them as parameters but that doesn't work...
The classes:
namespace Problema_test
{
class Masina
{
private string _nr_masina = string.Empty;
private string _valoare = string.Empty;
private string _an_fabricatie = string.Empty;
public Masina(string nr_masina,string valoare, string an_fabricatie)
{
_nr_masina = nr_masina;
_valoare = valoare;
_an_fabricatie = an_fabricatie;
}
public string Numar
{
get { return _nr_masina; }
set { _nr_masina = value; }
}
public string Valoare
{
get { return _valoare; }
set { _valoare = value; }
}
public string Anul
{
get { return _an_fabricatie; }
set { _an_fabricatie = value; }
}
}
class Destinatie
{
private string _cod_destinatie = string.Empty;
private string _adresa = string.Empty;
public Destinatie(string cod_destinatie, string adresa)
{
_cod_destinatie = cod_destinatie;
_adresa = adresa;
}
public string CodDest
{
get { return _cod_destinatie; }
set { _cod_destinatie = value; }
}
public string Adresa
{
get { return _adresa; }
set { _adresa = value; }
}
}
class MasinaDestinatie
{
// how can i make this work?
public MasinaDestinatie(string numarMasina, string codDest)
{
}
}
}
You can store the values inside properties
class MasinaDestinatie
{
public string Numar {get;set;}
public string CodDest {get;set;}
public MasinaDestinatie(string numarMasina, string codDest)
{
Numar = numarMasina;
CodDest = codDest;
}
}
To use the class you have do something like this
var masina = new Masina("Dacia","2000","1992");
var destinatie = new Destinatie("123", "Romania");
var masinaDestinatie = new MasinaDestinatie(masina.Numar, destinatie.CodDest);
Solution 2: As #blas-soriano sugested you can store the reference of the objects (Masina, Destinatie), this way you won't have problems (i.e. CodDest exist only in MasinaDestinatie but not in Destinatie, and many others).
class MasinaDestinatie
{
private Masina _masina {get;set;}
private Destinatie _destinatie {get;set;}
public string Numar { get { return _masina.Numar; } }
public string CodDest { get { return _destinatie.CodDest; } }
public MasinaDestinatie(Masina masina, Destinatie destinatie)
{
_masina = masina;
_destinatie = destinatie;
}
}
To use the class you have do something like this
var masina = new Masina("Dacia","2000","1992");
var destinatie = new Destinatie("123", "Romania");
var masinaDestinatie = new MasinaDestinatie(masina, destinatie);

How to use MetadataTypeAttribute with extended classes

I want to add a DisplayAttribute to the Client entity (from another project), but don't want to pollute my entity with attributes specific to MVC or a UI layer. So I planned to add the DisplayAttribute by applying a metadata class to a view model inheriting from the entity
If I inherit from the Client entity and then try to use the MetadataTypeAttribute to add a display attribute, it doesn't show up in the browser. Does anyone know how I can achieve the separation and the functionality of being able to add metadata to my entities?
The Client entity class:
public class Client
{
private string firstName;
private string lastName;
private string homeTelephone;
private string workTelephone;
private string mobileTelephone;
private string emailAddress;
private string notes;
public Title Title { get; set; }
public string FirstName
{
get { return this.firstName ?? string.Empty; }
set { this.firstName = value; }
}
public string LastName
{
get { return this.lastName ?? string.Empty; }
set { this.lastName = value; }
}
public string FullName
{
get
{
List<string> nameParts = new List<string>();
if (this.Title != Title.None)
{
nameParts.Add(this.Title.ToString());
}
if (this.FirstName.Length > 0)
{
nameParts.Add(this.FirstName.ToString());
}
if (this.LastName.Length > 0)
{
nameParts.Add(this.LastName.ToString());
}
return string.Join(" ", nameParts);
}
}
public Address Address { get; set; }
public string HomeTelephone
{
get { return this.homeTelephone ?? string.Empty; }
set { this.homeTelephone = value; }
}
public string WorkTelephone
{
get { return this.workTelephone ?? string.Empty; }
set { this.workTelephone = value; }
}
public string MobileTelephone
{
get { return this.mobileTelephone ?? string.Empty; }
set { this.mobileTelephone = value; }
}
public string EmailAddress
{
get { return this.emailAddress ?? string.Empty; }
set { this.emailAddress = value; }
}
public string Notes
{
get { return this.notes ?? string.Empty; }
set { this.notes = value; }
}
public Client()
{
this.Address = new Address();
}
}
The ClientViewModel view model class:
[MetadataType(typeof(ClientMetaData))]
public class ClientViewModel : Client
{
internal class ClientMetaData
{
[Display(ResourceType = typeof(ResourceStrings), Name = "Client_FirstName_Label")]
public string FirstName { get; set; }
}
}
I think you have change the typeof parameter to:
[MetadataType(typeof(ClientViewModel.ClientMetaData))]
public class ClientViewModel : Client
{
internal class ClientMetaData
{
[Display(ResourceType = typeof(ResourceStrings), Name = "Client_FirstName_Label")]
public string FirstName { get; set; }
}
}
For .Net Core 6.0 use
[ModelMetadataType(typeof(ClientViewModel.ClientMetaData))]
insead of
[MetadataType(typeof(ClientViewModel.ClientMetaData))]

Can I use LINQ To Search an inner list in a List of Lists?

I have these classes:
public class ZoneMember
// a zone member is a member of a zone
// zonemembers have ports, WWPNs, aliases or all 3
{
private string _Alias = string.Empty;
public string MemberAlias {get{return _Alias;} set{_Alias = value; } }
private FCPort _Port = null;
public FCPort MemberPort { get { return _Port; } set { _Port = value; } }
private string _WWPN = string.Empty;
public string MemberWWPN { get { return _WWPN; } set { _WWPN = value; } }
private bool _IsLoggedIn;
public bool IsLoggedIn { get { return _IsLoggedIn; } set { _IsLoggedIn = value; } }
private string _FCID;
public string FCID {get{return _FCID;} set{ _FCID=value; } }
}
public class Zone
{
public List<ZoneMember> MembersList = new List<ZoneMember>();
private string _ZoneName;
public string zoneName{ get{return _ZoneName;} set{_ZoneName=value;} }
public Zone(string n) { zoneName=n; }
}
public class ZoneSet
{
private string _ZoneSetName;
private int _VSANNum;
public string ZoneSetName{get{ return _ZoneSetName;} set{_ZoneSetName=value;} }
public int VSANNum{ get{ return _VSANNum;} set{_VSANNum=value;} }
public bool isActive;
public List<Zone> ZoneList = new List<Zone>();
}
I want to find all the zones in a Zoneset that have a zone member with a specific value for a property in the MembersList.
I know something like this will work - in this case I am searching on the WWPN property:
// assumes myZoneSet has already been instantiated ad has zones in it
// and inputWWPN in the select statement has the value we want
List<Zone> myZoneList = new List<Zone>();
foreach (Zone z in myZoneset)
{
var zm=null;
zm = from member in z.MembersList where member.MemberWWPN == inputWWPN select member;
// if we find a matching member, add this zone to the list
if (zm != null)
{ myZoneList.Add(z);
}
}
Is there a way to use LINQ to do the entire thing? I am not sure what the terminology would be in database terms.
This small query should be all you need:
var myZoneList = myZoneSet.ZoneList
.Where(z => z.Any(member => member.MemberWWPN == inputWWPN))
.ToList();
Try this -
List<Zone> listOfZone = zoneSet.ZoneList.Where(e => e.Any(p => p.MemberWWPN == inputWWPN)).ToList();
myZoneList =myZoneSet.SelectMany(z => z.MembersList).Where(m => m.MemberWWPN == "somestring").ToList();
I hope this will help.

Categories

Resources