Self-Reference in OOP & C# - c#

consider below table :
FkName SchemaName Table Column RefTable RefColumn
FK_Factory_Person dbo Factory PersonId Person Id
FK_Car_Person dbo Car PersonId Person Id
FK_Factory_Car dbo Factory CarId Car Id
I want to create Dependency class for saving the dependent data
so I wrote a self-reference class that any dependency can have dependencies.
public class Dependency
{
public string TableName { get; set; } // RefTable
public string ColumnName { get; set; } //RefColumn
public List<Dependency> Dependencies { get; set; } // Table
}
but I dont know how fill class :
- TableName=Person , ColumnName=Id , Dependencies=Factory,Car
--TableName=Car , ColumnName=Id , Dependencies=Factory
Factory
'
'---- Person
'---- Car
Car
'
'---- Person
Can anyone help me for filing Dependency class recursively ?

SOLUTION:
public class Link
{
public string FKName { get; set; }
public string SchemaName { get; set; }
public string Table { get; set; }
public string Column { get; set; }
public string RefTable { get; set; }
public string RefColumn { get; set; }
}
public class Dependency
{
public string TableName { get; set; } // RefTable
public string ColumnName { get; set; } //RefColumn
public List<Dependency> Dependencies { get; set; } // Table
}
private static void ProcessItem(Dependency target, List<Dependency> dictionary)
{
if(target.Dependencies != null)
foreach(var dep in target.Dependencies)
{
var children = dictionary.Where(x => x.TableName == dep.TableName).FirstOrDefault();
dep.Dependencies = children == null ? null : children.Dependencies;
ProcessItem(dep, dictionary);
}
}
public static List<Dependency> ProcessItems(List<Link> links)
{
var initial = links.GroupBy(x => new { x.RefTable, x.RefColumn })
.Select(x => new Dependency {
TableName = x.Key.RefTable,
ColumnName = x.Key.RefColumn,
Dependencies = x.Select(y => new Dependency {
TableName = y.Table,
ColumnName = y.Column
}).ToList()
}).ToList();
var js = new JavaScriptSerializer();
var temp = js.Deserialize<List<Dependency>>(js.Serialize(initial));
initial.ForEach(x => ProcessItem(x, temp));
return initial;
}
IMPLEMENTATION:
var links = new List<Link> {
new Link { FKName = "FK_Factory_Person", SchemaName = "dbo", Table = "Factory", Column = "PersonId", RefTable = "Person", RefColumn = "Id" },
new Link { FKName = "FK_Car_Person", SchemaName = "dbo", Table = "Car", Column = "PersonId", RefTable = "Person", RefColumn = "Id" },
new Link { FKName = "FK_Factory_Car", SchemaName = "dbo", Table = "Factory", Column = "CarId", RefTable = "Car", RefColumn = "Id" },
new Link { FKName = "FK_TEST", SchemaName = "dbo", Table = "Person", Column = "TestId", RefTable = "Test", RefColumn = "Id" }
};
var answer = ProcessItems(links);
P.S. If you have circular dependency, StackOveflowException will be
thrown.

Related

How can I get latest employee ID (string) from the list of employees using .net web api Get call

I am using Entity Framework
My EmployeeDto class is :
public class EmployeeDto
{
[DataMember]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int SerialNumber { get; set; }
[DataMember]
[Key]
[Required]
public string ID { get; set; }
[DataMember]
[Required]
public string FirstName { get; set; }
[DataMember]
public string MiddleName { get; set; }
[DataMember]
[Required]
public string LastName { get; set; }
}
My Dto class is EmployeeDto and Dal class is named as Employee. I want to get the maximum value of EmployeeID from the database and provide it to frontend through Get call .
My Get call to get the list of all employees is :
public List<EmployeeDto> GetAllEmployees()
{
var employeeDto = new List<EmployeeDto>();
using (EmployeeDataEntities entities = new EmployeeDataEntities())
{
var employeeData = entities.Employees.ToList().Where(e => e.IsActive == true);
List<Employee> emp = employeeData.ToList();
//emp.FindLastIndex(e => e.)
employeeDto = Mapper.Map<List<Employee>,List<EmployeeDto>>(emp);
};
return employeeDto;
}
This is my GetLatestEmployeeByID code :
public int GetEmployeeLatestID(EmployeeDto employeeDto)
{
using (EmployeeDataEntities entities = new EmployeeDataEntities())
{
var employeeData = entities.Employees.ToList().Where(e => e.IsActive == true);
List<Employee> emp = employeeData.ToList();
emp.FindLastIndex(e => e.ID);
}
}
I have tried a couple of solutions and i end up with this one:
var a = new List<EmployeeDto>()
{
new EmployeeDto()
{
SerialNumber = 1,
ID = "AB01",
FirstName = "Ala",
MiddleName = "b",
LastName = "ala"
},
new EmployeeDto()
{
SerialNumber = 2,
ID = "AB02",
FirstName = "Ala",
MiddleName = "b",
LastName = "ala"
},new EmployeeDto()
{
SerialNumber = 3,
ID = "AB03",
FirstName = "Ala",
MiddleName = "b",
LastName = "ala"
}
};
// biggestIdAsInt = 230 a.max returns the max value after the calculations
var biggestIdAsInt = a.Max(employee => Encoding.ASCII.GetBytes(employee.ID) // get Employee Id as byte array
.Sum(b => b)); // summ the bytes for each employee
// 230
var substractedNumberFromBiggestId = Regex.Match(a.FirstOrDefault(x => x.ID.ToCharArray().Sum(y => y) == biggestIdAsInt).ID, #"\d+").Value;
Console.WriteLine(substractedNumberFromBiggestId);
I have put comments to make the code a little bit clearer.

How to Convert List<T> to BsonArray to save a MongoDB Document

I'm having an Model Class, I need to Save it in a MongoDB Collection.
My Model Class:
public Class Employee
{
public string EmpID { get; set; }
public string EmpName { get; set; }
public List<Mobile> EmpMobile { get; set; }
}
public Class Mobile
{
public string MobID { get; set; }
public string MobNumber { get; set; }
public bool IsPreferred { get; set; }
}
The Values are
Employee EmpInfo = new Employee()
{
EmpID = "100",
EmpName = "John",
EmpMobile = new List<Mobile>()
{
{ MobNumber = "55566610", IsPreferred = true },
{ MobNumber = "55566611", IsPreferred = false },
}
}
BsonDocument _employee = new BsonDocument()
{
{ "Emp_ID", EmpInfo.EmpID },
{ "Emp_Name", EmpInfo.EmpName },
{ "Emp_Mobile", new BsonArray (EmpInfo.EmpMobile.Select(m => new
{
MobID = new ObjectId(),
MobNumber = m.MobNumber,
IsPreferred = m.IsPreferred
})) }
};
var collection = _database.GetCollection<BsonDocument>("EmployeeInfo");
collection.InsertOne(_employee);
I wish to save the above EmpInfo of type Employee in a MongoDB. But I can't able to create a BsonDocument. Kindly assist me is there is anything wrong in the above code. If yes kindly assist me.
there is no need to serialize to bson document
You can use TYPED collection and just insert data
Please see attached code snipet with updated class structure
void Main()
{
// To directly connect to a single MongoDB server
// or use a connection string
var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("test");
var collectionEmpInfo = database.GetCollection<Employee>("Employee");
Employee EmpInfo = new Employee
{
EmpID = "100",
EmpName = "John",
EmpMobile = new List<Mobile>
{
new Mobile{ MobNumber = "55566610", IsPreferred = true, MobID = ObjectId.GenerateNewId() },
new Mobile{ MobNumber = "55566611", IsPreferred = false, MobID = ObjectId.GenerateNewId() },
}
};
collectionEmpInfo.InsertOne(EmpInfo);
var empList = collectionEmpInfo.Find(new BsonDocument()).ToList();
empList.Dump(); //dump is used in linqPad
}
public class Employee
{
public ObjectId Id { get; set; }
public string EmpID { get; set; }
public string EmpName { get; set; }
public List<Mobile> EmpMobile { get; set; }
}
public class Mobile
{
public ObjectId MobID { get; set; }
public string MobNumber { get; set; }
public bool IsPreferred { get; set; }
}
In addition to answer above, I can suggest following code if you want to deal directly with Bson for some reason:
BsonDocument _employee = new BsonDocument()
{
{ "Emp_ID", EmpInfo.EmpID },
{ "Emp_Name", EmpInfo.EmpName },
{ "Emp_Mobile", BsonArray.Create(EmpInfo.EmpMobile.Select(m => new BsonDocument()
{
{ "MobID" , new ObjectId() },
{ "MobNumber", m.MobNumber },
{ "IsPreferred", m.IsPreferred }
})) }
};
The reason of the error you've got is that BsonArray.Create creates an array of values, not an array of objects. See this question for details.

How to map nested Property with Automapper

I am trying to map Student with StudentDto, this is what I am doing but it is complaining about the nested property which is of type List<StudentContact>
Both the objects, StudentDto and Student have exactly the same properties, this is what i am using to try to map the objects.
var config = new MapperConfiguration(
cfg => cfg.CreateMap<StudentDto, Student>());
var mapper = config.CreateMapper();
var driverActivationResponse = mapper.Map <List<Student> > (studentDto);// "studentDto" is List<StudentDto>
my classes
public class StudentDto
{
public StudentDto()
{
if(StudentContacts==null) StudentContacts=new List<StudentContact>();
}
public string Id { get; set; }
public List<StudentContact> StudentContacts { get; set; }
}
public class Student
{
public Student()
{
if(StudentContacts==null) StudentContacts=new List<StudentContact>();
}
public string Id { get; set; }
public List<StudentContact> StudentContacts { get; set; }
}
public class StudentContact
{
public string ContactName { get; set; }
public string PrimaryContactNo { get; set; }
}
This should help -
AutoMapper.Mapper.CreateMap<Student, StudentDto>()
.ForMember(a => a.StudentContacts, b => b.ResolveUsing(c => c.StudentContacts));
var map = Mapper.Map<StudentDto>(new Student
{
Id = "100",
StudentContacts = new List<StudentContact>
{
new StudentContact{ContactName = "test",PrimaryContactNo = "tset"}
}
});
you cannot map like mapper.Map <List<Student>>(studentDto);. The top level member cannot be a list when using automapper.
Does it help to specify the source collection type and destination collection type in your Map call?
var driverActivationResponse = mapper.Map<List<Student>, List<StudentDto>>(studentDto);
It looks like the AutoMapper code you have is correct. If you're still getting an error, something else must be wrong. Perhaps your studentDto is not really a List<StudentDto>?
In any case, here's an entire example that works without error:
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
namespace ConsoleSandbox
{
class Program
{
public static void Main()
{
var config = new MapperConfiguration(
cfg => cfg.CreateMap<StudentDto, Student>());
var mapper = config.CreateMapper();
var studentDtos = new[]
{
new StudentDto
{
Id = "1",
StudentContacts = new[]
{
new StudentContact { ContactName = "Dan", PrimaryContactNo = "123" },
new StudentContact { ContactName = "Stan", PrimaryContactNo = "456" },
}.ToList()
},
new StudentDto
{
Id = "2",
StudentContacts = new[]
{
new StudentContact { ContactName = "Foo", PrimaryContactNo = "789" },
new StudentContact { ContactName = "Bar", PrimaryContactNo = "101112" },
}.ToList()
},
}.ToList();
var driverActivationResponse = mapper.Map<List<Student>>(studentDtos);
Console.WriteLine($"Contacts Count: {driverActivationResponse.Count}");
Console.ReadKey();
}
}
public class StudentDto
{
public string Id { get; set; }
public List<StudentContact> StudentContacts { get; set; }
public StudentDto()
{
if (StudentContacts == null) StudentContacts = new List<StudentContact>();
}
}
public class Student
{
public string Id { get; set; }
public List<StudentContact> StudentContacts { get; set; }
public Student()
{
if (StudentContacts == null) StudentContacts = new List<StudentContact>();
}
}
public class StudentContact
{
public string ContactName { get; set; }
public string PrimaryContactNo { get; set; }
}
}

Get a particular instance of a class

I have created a model for UnitOfMeasure (UOM) and a model for ingredient where I would like to use UOM to enter a default UOM for the ingredient.
public class IngredientModel
{
public int Id { get; set; }
public string Name { get; set; }
public UnitOfMeasureModel DefaultUOM { get; set; }
}
public class UnitOfMeasureModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Abbreviation { get; set; }
}
I would like to use the Name property in the IngredientModel.
In configure.cs I have put this code to create some default data for the database:
protected override void Seed(RecipeApplication.Models.RecipeApplicationDb context)
{
if (!context.UnitOfMeasures.Any())
{
context.UnitOfMeasures.AddOrUpdate(
u => u.Id,
new UnitOfMeasureModel { Name = "Gram", Abbreviation = "g" },
new UnitOfMeasureModel { Name = "Kilogram", Abbreviation = "kg"},
new UnitOfMeasureModel { Name = "Milligram", Abbreviation = "mg" }
);
}
if (!context.Ingredients.Any())
{
context.Ingredients.AddOrUpdate(
i => i.Id,
new IngredientModel { Name = "Italiaanse Ham", DefaultUOM =
);
}
}
I did not enter anything yet at default UOM because that is where I got stuck.
Could someone help me with this issue?
I'm assuming you just want to be able to access one of the UnitOfMeasureModel classes in both the UnitOfMeasures.AddOrUpdate and the UnitOfMeasures.AddOrUpdate methods. To do this create the instance before the calls and use that same instance in each AddOrUpdate method like so.....
protected override void Seed(RecipeApplication.Models.RecipeApplicationDb context)
{
var defaultUOM = new UnitOfMeasureModel { Name = "Gram", Abbreviation = "g" };
if (!context.UnitOfMeasures.Any())
{
context.UnitOfMeasures.AddOrUpdate(
u => u.Id,
defaultUOM,
new UnitOfMeasureModel { Name = "Kilogram", Abbreviation = "kg"},
new UnitOfMeasureModel { Name = "Milligram", Abbreviation = "mg" }
);
}
if (!context.Ingredients.Any())
{
context.Ingredients.AddOrUpdate(
i => i.Id,
new IngredientModel { Name = "Italiaanse Ham", DefaultUOM = defaultUOM
);
}
}
obviously you can change if gram is not the correct default

Best approach to insert on many to many tables using Identity columns on ServiceStack ORMLite

Yesterday I found this great ORM and would like to perform some testings on more complex stuff than the samples provided on github.
This is the model I'm using
class BaseClass
{
[AutoIncrement]
public int Id { get; set; }
[StringLength(200)]
public string Name { get; set; }
}
[Alias("artist")]
class Artist : BaseClass
{
}
[Alias("genre")]
class Genre : BaseClass
{
}
[Alias("artistgenre")]
class ArtistGenre
{
[PrimaryKey]
public int Id { get; set; }
[Alias("idgenre")]
[References(typeof(Genre))]
public int IdGenre { get; set; }
[Alias("idartist")]
[References(typeof(Artist))]
public int IdArtist { get; set; }
}
And this is what I'm trying to achieve (although it doesn't work since the Identity values are unknown when inserting into artistgenre table).
if (dbConn.TableExists("artistgenre"))
dbConn.DropTable<ArtistGenre>();
if (dbConn.TableExists("artist"))
dbConn.DropTable<Artist>();
if (dbConn.TableExists("genre"))
dbConn.DropTable<Genre>();
dbConn.CreateTables(false, typeof(Artist), typeof(Genre), typeof(ArtistGenre));
var genres = new List<Genre>();
genres.Add(new Genre() { Name = "Rock" });
genres.Add(new Genre() { Name = "Pop" });
genres.Add(new Genre() { Name = "Jazz" });
genres.Add(new Genre() { Name = "Classic" });
genres.Add(new Genre() { Name = "Bossanova" });
var artists = new List<Artist>();
artists.Add(new Artist() { Name = "Rush" });
artists.Add(new Artist() { Name = "Queen" });
artists.Add(new Artist() { Name = "Pat Metheny" });
var ag = new List<ArtistGenre>();
var a = artists.FirstOrDefault(c => c.Name == "Rush");
var g = genres.FirstOrDefault(c => c.Name == "Rock");
ag.Add(new ArtistGenre() { IdArtist = a.Id, IdGenre = g.Id });
dbConn.SaveAll<Artist>(artists);
dbConn.SaveAll<Genre>(genres);
dbConn.SaveAll<ArtistGenre>(ag);
Is there a simple solution other than adding each row and obtaining its Identity values?
Thanks.
OrmLite doesn't currently populate the model with the auto-incrementing id atm. The way you obtain the autoincrement Id is to use db.GetLastInsertId() after each insert, e.g:
artists.ForEach(artist => {
db.Insert(artist);
artist.Id = db.GetLastInsertId();
});
I recommend wrapping this in an extension method to make this nicer to work with.

Categories

Resources