Why am I not getting results when performing an intersection? - c#

Users class:
public class User
{
public int ID { get; set; }
public string Email { get; set; }
}
Code:
var usersL = new List<User>()
{
new User{ID = 1,Email = "abc#foo.com"},
new User{ID = 2,Email = "def#foo.com"}
};
var usersR = new List<User>()
{
new User{ID = 1,Email = "abc#foo.com"},
new User{ID = 2,Email = "def#foo.com"}
};
var both = (from l in usersL select l)
.Intersect(from users in usersR select users);
foreach (var r in both)
Console.WriteLine(r.Email);
Which returns 0 results.
I know I can accomplish something similar by using join, but I want to use Intersect because A) this is eventually going to work on some DB code and we want to use this function (too long to go into why) and B) I'm just plain curious as to why Intersect isn't working here.
var both = from l in usersL
join r in usersR on l.ID equals r.ID
select l;

.Net provides comparison logic for predefined types. In case of your join query your were joining (comparing) two IDs which were of type Int (predefined types)
var both = from l in usersL
join r in usersR on l.ID equals r.ID
select l;
In case of your intersect query you are trying to compare two user defined custom objects of type User. Hence you need to provide your own custom compare implementation logic.
There are 2 ways to tackle this...
Option 1:
Implement the IEqualityComparer
public class User
{
public int ID { get; set; }
public string Email { get; set; }
}
public class MyEqualityComparer : IEqualityComparer<User>
{
public bool Equals(User x, User y)
{
if (object.ReferenceEquals(x, y))
return true;
if (x == null || y == null)
return false;
return x.ID.Equals(y.ID) &&
x.Email.Equals(y.Email);
}
public int GetHashCode(User u)
{
return new { u.ID, u.Email }.GetHashCode();
}
}
class Program
{
static void Main(string[] args)
{
var usersL = new List<User>()
{
new User{ID = 1,Email = "abc#foo.com"},
new User{ID = 2,Email = "def#foo.com"}
};
var usersR = new List<User>()
{
new User{ID = 1,Email = "abc#foo.com"},
new User{ID = 2,Email = "def#foo.com"}
};
var both = (from l in usersL select l)
.Intersect(from users in usersR select users, new MyEqualityComparer());
foreach (var r in both)
Console.WriteLine(r.Email);
}
}
Option 2: Override the Equals and GetHashcode methods in the custom object itself
public class User
{
public int ID { get; set; }
public string Email { get; set; }
public override bool Equals(Object obj)
{
// Check for null values and compare run-time types.
if (obj == null || GetType() != obj.GetType())
return false;
User x = (User)obj;
return (ID == x.ID) && (Email == x.Email);
}
public override int GetHashCode()
{
return new { ID, Email }.GetHashCode();
}
}
class Program
{
static void Main(string[] args)
{
var usersL = new List<User>()
{
new User{ID = 1,Email = "abc#foo.com"},
new User{ID = 2,Email = "def#foo.com"}
};
var usersR = new List<User>()
{
new User{ID = 1,Email = "abc#foo.com"},
new User{ID = 2,Email = "def#foo.com"}
};
var both = (from l in usersL select l)
.Intersect(from users in usersR select users);
foreach (var r in both)
Console.WriteLine(r.Email);
}
}
Hope this helps.

This is in response to #sundeep who said "Now regards to your 2nd question... " (I wish you could link to comments) -- I'm just creating a new answer as I don't want to ruin the context of my original question
User class implementing IEqualityComparer
public class User : IEqualityComparer<User>
{
public int ID { get; set; }
public string Email { get; set; }
public bool Equals(User x, User y)
{
if (object.ReferenceEquals(x, y))
return true;
if (x == null || y == null)
return false;
return x.ID.Equals(y.ID) &&
x.Email.Equals(y.Email);
}
public int GetHashCode(User obj)
{
return new { obj.ID, obj.Email }.GetHashCode();
}
}
Intersection returns no rows:
var usersL = new List<User>()
{
new User{ID = 1,Email = "abc#foo.com"},
new User{ID = 2,Email = "def#foo.com"}
};
var usersR = new List<User>()
{
new User{ID = 1,Email = "abc#foo.com"},
new User{ID = 2,Email = "def#foo.com"}
};
var both = (from l in usersL select l)
.Intersect(from users in usersR select users);
foreach (var r in both)
Console.WriteLine(r.Email);

Related

Partition graph by connection degree

I would to ask if there is already algorithms for graphs that partition graphs into subgraphs like the screenshot attached:
Graph has edges
A-B,B-C,C-D, D-E, C-F, F-G
I need to partition it to 3 parts since vertex C has degree of 3:
A-B-C
C-D-E
C-F-G
First I was thinking that I can remove C node and disconnect graph using typical methods. But maybe there already known method to partition graphs by nodes degree?
I wrote a simple algorithm for this. Please note that the graph is needed to be ordered
public static void Main()
{
Console.WriteLine("Hello World");
var str = "A-B,B-C,C-D,D-E,C-F,F-G";
var resultSet = Graph(str.Split(','), '-');
}
public static string[] Graph(string[] s, char delimiter)
{
var resultSet = new List<string>();
var prevOperLeft = "";
var prevOperRight = "";
foreach (var part in s)
{
var oper = part.Split(delimiter);
var left = oper[0];
var right = oper[1];
if (prevOperRight == left)
{
resultSet.Add(string.Format("{0}{1}{2}{3}{4}", prevOperLeft, delimiter, left, delimiter, right));
prevOperLeft = prevOperRight = "";
}
else
{
prevOperLeft = left;
prevOperRight = right;
}
}
return resultSet.ToArray();
}
https://dotnetfiddle.net/e3kmpR
More generic example with LinkedList
public static IList<LinkedList<T>> Graph2<T>(LinkedList<T> ll) where T: class
{
var resultSet = new List<LinkedList<T>>();
T prevOperLeft = null;
T prevOperRight = null;
while (ll.Count > 0)
{
var left = ll.First.Value;
ll.RemoveFirst();
var right = ll.First.Value;
ll.RemoveFirst();
if (prevOperRight != null && prevOperRight.Equals(left))
{
resultSet.Add(new LinkedList<T>(new []{ prevOperLeft, left, right }));
prevOperLeft = prevOperRight = null;
}
else
{
prevOperLeft = left;
prevOperRight = right;
}
}
return resultSet;
}
public static void Main()
{
var A = new MyClass {Name = "A"};
var B = new MyClass {Name = "B"};
var C = new MyClass {Name = "C"};
var D = new MyClass {Name = "D"};
var E = new MyClass {Name = "E"};
var F = new MyClass {Name = "F"};
var G = new MyClass {Name = "G"};
List<MyClass> list = new List<MyClass>
{
A,B,B,C,C,D,D,E,C,F,F,G
};
LinkedList<MyClass> ll = new LinkedList<MyClass>(list);
var resultSet2 = Graph2(ll);
}
class MyClass
{
public string Name { get; set; }
}

ObjectDisposedException EF Error

I´m having a problem because always I press the Action Button I got the this Exception.
This part is giving me a error
public void InserirComCopia(TabelaPreco tabPrec, string copiarDe)
{
var lista = new List<PrecoProduto>();
var tb = InserirTabelaVazia(tabPrec);
var rep = new PrecoRepositorio();
lista = rep.ObterPrecoPorTabela(Int32.Parse(copiarDe));
var ls = new List<PrecoProduto>();
using (var context = new indigo.DataModel.IndigoContext())
{
foreach (var item in lista)
{
var p = new PrecoProduto()
{
preco = item.preco,
TabPreco = tb,
TabPrecoId = tb.Id,
Produto = item.Produto,
ProdutoId = item.ProdutoId
};
ls.Add(p);
}
context.PrecoProduto.AddRange(ls);
context.SaveChanges();
}
}
And this is all my controller:
public TabelaPreco ObterTablePrecoPorID(int Id, List<TabelaPreco> tabelaPreco)
{
return tabelaPreco.Where(t => t.Id == Id)
.FirstOrDefault();
}
public List<TabelaPreco> ObterTodasAsTabelas()
{
List<TabelaPreco> model = new List<TabelaPreco>();
using (var context = new indigo.DataModel.IndigoContext())
{
model = context.TabelaPreco.ToList();
}
return model;
}
public List<TabelaPreco> Buscar(string busca)
{
List<TabelaPreco> model = new List<TabelaPreco>();
using (var context = new indigo.DataModel.IndigoContext())
{
model = context.TabelaPreco.Where(tb => tb.Desc.Contains(busca)).ToList();
}
return model;
}
public TabelaPreco InserirTabelaVazia(TabelaPreco tab)
{
using (var context = new indigo.DataModel.IndigoContext())
{
context.TabelaPreco.Add(tab);
context.SaveChanges();
return tab;
}
}
public void Deletar(int id)
{
var tabela = new TabelaPreco();
using (var context = new indigo.DataModel.IndigoContext())
{
tabela = context.TabelaPreco.Where(tb => tb.Id == id)
.FirstOrDefault();
context.TabelaPreco.Remove(tabela);
context.SaveChanges();
}
}
public void InserirComCopia(TabelaPreco tabPrec, string copiarDe)
{
var lista = new List<PrecoProduto>();
var tb = InserirTabelaVazia(tabPrec);
var rep = new PrecoRepositorio();
lista = rep.ObterPrecoPorTabela(Int32.Parse(copiarDe));
var ls = new List<PrecoProduto>();
using (var context = new indigo.DataModel.IndigoContext())
{
foreach (var item in lista)
{
var p = new PrecoProduto()
{
preco = item.preco,
TabPreco = tb,
TabPrecoId = tb.Id,
Produto = item.Produto,
ProdutoId = item.ProdutoId
};
ls.Add(p);
}
context.PrecoProduto.AddRange(ls);
context.SaveChanges();
}
}
public TabProdListModel PegarProdutosDaTabela(int id)
{
using (var context = new indigo.DataModel.IndigoContext())
{
var modelTab = context.TabelaPreco.Where(tb => tb.Id == id).First();
var modelProd = context.Produto.ToList();
var model = context.TabelaPreco
.Where(t => t.Id == id)
.Join(
context.PrecoProduto,
t => t.Id,
x => x.TabPrecoId,
(t, x) => new { t, x }
)
.Join(
context.Produto,
p => p.x.ProdutoId,
y => y.Id,
(p, y) => new ListProduto
{
produtoId = y.Id,
produto = y.Nome,
precoProduto = p.x.preco,
Cor = y.Cor,
Tamanho = y.Tamanho
}
)
.ToList();
var ls = new TabProdListModel()
{
tabela = modelTab,
Produtos = modelProd,
TdProdutos = model
};
var prod = ls.Produtos.ToList();
if (modelProd.Count() != 0)
foreach (var item in ls.Produtos)
{
foreach (var td in ls.TdProdutos)
{
if (item.Id == td.produtoId)
{
prod.Remove(item);
break;
}
}
}
ls.Produtos = prod;
return ls;
}
}
public void AdicionarProdTab(int Produto, double Valor, int Tabela)
{
using(var context = new indigo.DataModel.IndigoContext())
{
var produto = context.Produto.Where(p => p.Id == Produto).FirstOrDefault();
var tabela = context.TabelaPreco.Where(tp => tp.Id == Tabela).FirstOrDefault();
var precoProduto = new PrecoProduto()
{
preco = Valor,
Produto = produto,
TabPreco = tabela
};
context.PrecoProduto.Add(precoProduto);
context.SaveChanges();
}
}
public void EditarProdutoTabela(int ProdutoId, double valor, int tabela)
{
using (var context = new indigo.DataModel.IndigoContext())
{
var precoProduto = context.PrecoProduto.Where(x => x.ProdutoId == ProdutoId && x.TabPrecoId == tabela).FirstOrDefault();
precoProduto.preco = valor;
context.PrecoProduto.Attach(precoProduto);
var Entry = context.Entry(precoProduto);
Entry.Property(e => e.preco).IsModified = true;
context.SaveChanges();
}
}
public void Remover(int id)
{
}
Please help me!
PS: Sorry for my bad english, I´m a Brazilian code student
UPDATE:
My repository:
public List<PrecoProduto> ObterPrecoPorTabela(int copiarDe)
{
var Precos = new List<PrecoProduto>();
using (var context = new indigo.DataModel.IndigoContext())
{
Precos = context.PrecoProduto.Where(pp => pp.TabPrecoId == copiarDe).ToList();
}
return Precos;
}
On this line: TabPreco = tb, and then here Produto = item.Produto, I'm not positive you can do. You are taking an object that's correctly connected to your database context and trying to attach it to something that's no longer attached. Perhaps try removing those lines to see if it helps? I can't imagine why you'd need to both set those and set the IDs. You should only need to do one or the other.

C# / Linq: detected differences between two list typed

I would like to detect if some data changed using Linq.
I have this class:
public class MyData
{
public string Nombre {get; set;}
public string Tipo {get; set;}
public int Longitud {get; set;}
}
I have a list typed of that class which I can change the data and another one it is the copy before to change.
Typed structure:
List<MyData> data = new List<MyData>();
// suppose I load data here in data variable.
List<MyData> mycopy = data;
var mydatatochange = data.Where(...).ToList();
mydatatochange
...or...
MyData info = new MyData();
info.Nombre = "aaa";
info.Tipo = "something";
data.Add(info);
Now I would like to see if between data and mycopy have some kind of differences.
I am trying to use it using Linq.
Here is a code that detects added, deleted and changed items:
List<MyData> lst = new List<MyData>();
lst.Add(new MyData()
{
Longitud = 1,
Tipo = "123",
Nombre = "n1"
});
lst.Add(new MyData()
{
Longitud = 1,
Tipo = "456",
Nombre = "n1"
});
var cloned = lst.ToList();
Dictionary<MyData, Tuple<string, string, int>> originalValues = new Dictionary<MyData, Tuple<string, string, int>>();
foreach (var item in cloned)
originalValues[item] = new Tuple<string, string, int>(item.Nombre, item.Tipo, item.Longitud);
cloned.Remove(lst[0]);
cloned.Add(new MyData()
{
Longitud = 2,
Nombre = "aaaaaa",
Tipo = "gggg"
});
var added = (from p in cloned
join orig in lst
on p equals orig into left
from orig in left.DefaultIfEmpty()
where orig == null
select p).ToList();
var deleted = (from orig in lst
join c in cloned
on orig equals c into left
from c in left.DefaultIfEmpty()
where c == null
select orig).ToList ();
var changed = (from orig in lst
join c in cloned
on orig equals c
where originalValues[orig].Item1 != orig.Nombre ||
originalValues[orig].Item2 != orig.Tipo ||
originalValues[orig].Item3 != orig.Longitud
select orig
).ToList();
In order to check if one object equals another you can use object.Equals(otherObject), but...
In your example you do: List<MyData> mycopy = data; which will not be copy, but it will create pointer like object which will also change if you change data object. So in order to make it work:
1) Edit your MyData class with such code:
public class MyData
{
public MyData(string nombre, string tipo, int longitud)
{
Nombre = nombre;
Tipo = tipo;
Longitud = longitud;
}
public MyData(MyData itemToCopy)
{
Nombre = itemToCopy.Nombre;
Tipo = itemToCopy.Tipo;
Longitud = itemToCopy.Longitud;
}
public string Nombre { get; set; }
public string Tipo { get; set; }
public int Longitud { get; set; }
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj.GetType() != this.GetType())
{
return false;
}
return Equals((MyData)obj);
}
protected bool Equals(MyData other)
{
return string.Equals(this.Nombre, other.Nombre) && string.Equals(this.Tipo, other.Tipo) && this.Longitud == other.Longitud;
}
public override int GetHashCode()
{
unchecked
{
var hashCode = (this.Nombre != null ? this.Nombre.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.Tipo != null ? Tipo.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ this.Longitud;
return hashCode;
}
}
}
2) Create clone of list:
List<MyData> mycopy = new List<MyData>();
data.ForEach((item)=>
{
mycopy.Add(new MyData(item));
});
3) With this code you can do that to check if it equals:
var isEqual = data.Count == copy.Count;
if (isEqual)
{
isEqual = !data.Where((t, i) => !t.Equals(copy[i])).Any();
}

EF Code First: The Collection has been modified

Getting this error when try to add an item to my repositories/context:
Collection has been modified. Possibly the inventory operation is not performed.
What I'm trying to do
Campaign c = Campaignrepository.FindById(id);
if (c.LandingPage == null)
{
c.LandingPage = new Page() { Campaign = c, CampaignID = c.Campaignid };
PageRepository.Add(c.LandingPage);
}
if (c.RedeemPage == null)
{
c.RedeemPage = new RedeemPage() { Campaign = c, CampaignID = c.Campaignid };
PageRepository.Add(c.RedeemPage);
}
The Repository Add method:
public void Add(Page p)
{
pages.Add(p);
context.SaveChanges();
}
Update: still same error.
After applying the suggestions:
public ActionResult Edit(int id)
{
Campaign c = Campaignrepository.FindById(id);
Campaign newreferenceC = Campaignrepository.FindById(id);
if (c.LandingPage == null)
{
c.LandingPage = new Page() { Campaign = newreferenceC, CampaignID = newreferenceC.Campaignid };
PageRepository.Add(c.LandingPage);
}
if (c.RedeemPage == null)
{
c.RedeemPage = new RedeemPage() { Campaign = newreferenceC, CampaignID = newreferenceC.Campaignid };
PageRepository.Add(c.RedeemPage);
}
return View("Edit", Campaignrepository.FindById(id));
}
Manged to fix it with:
Page landingPage = new Page(c);
RedeemPage redeemPage = new RedeemPage(c);
PageRepository.Add(landingPage);
PageRepository.Add(redeemPage);
c.LandingPage = landingPage;
c.RedeemPage = redeemPage;
Campaignrepository.Update(c);

return LINQ to list<entity>?

List<PersonsInChargeEntity> picList = new List<PersonsInChargeEntity>();
List<ClientEntity> clientList = new List<ClientEntity>();
var returnList = (from PersonsInChargeEntity pic in picList
join ClientEntity client in clientList
on pic.ClientNumber equals client.ClientNumber
select new { ClientNumber = pic.ClientNumber, CompanyName = client.CompanyNameFull, AICGroupID = pic.AICStaffGroupID, RPStaffID = pic.RPStaffID, MPStaffID = pic.MPStaffID, CSPStaffID = pic.CSPStaffID, EQCRStaffID = pic.EQCRStaffID }).ToList<PicList>();
How can i convert my returnList to a List< entity>? below is my class for the entity.
public class PicList
{
int _ClientNumber = 0;
string _CompanyName = "";
int _AICGroupID = 0;
int _RPStaffID = 0;
int _MPStaffID = 0;
int _CSPStaffID = 0;
int _EQCRStaffID = 0;
public PicList()
{
}
public PicList(int ClientNumber, string CompanyName, int AICGroupID, int RPStaffID, int MPStaffID, int CSPStaffID, int EQCRStaffID)
{
_ClientNumber = ClientNumber;
_CompanyName = CompanyName;
_AICGroupID = AICGroupID;
_RPStaffID = RPStaffID;
_MPStaffID = MPStaffID;
_CSPStaffID = CSPStaffID;
_EQCRStaffID = EQCRStaffID;
}
public int ClientNumber
{
get { return _ClientNumber; }
set { _ClientNumber = value; }
}
public string CompanyName
{
get { return _CompanyName; }
set { _CompanyName = value.Trim(); }
}
public int AICGroupID
{
get { return _AICGroupID; }
set { _AICGroupID = value; }
}
public int RPStaffID
{
get { return _RPStaffID; }
set { _RPStaffID = value; }
}
public int MPStaffID
{
get { return _MPStaffID; }
set { _MPStaffID = value; }
}
public int CSPStaffID
{
get { return _CSPStaffID; }
set { _CSPStaffID = value; }
}
public int EQCRStaffID
{
get { return _EQCRStaffID; }
set { _EQCRStaffID = value; }
}
}
From my understanding of your problem, you require the result of the query to be a List<PicList>. To accomplish this, you need to select an instance of the concrete PicList type within your LINQ query rather than of an anonymous type. C# doesn't normally support duck-typing (with some exceptions); in particular, it's not possible to cast one type to another just because the two types happen to have similar property declarations.
I also observe that PicList has a public parameterless constructor, and that all the properties have public setters. So this should work fine:
var returnList = (from PersonsInChargeEntity pic in picList
join ClientEntity client in clientList
on pic.ClientNumber equals client.ClientNumber
select new PicList // no longer an anonymous type
{
ClientNumber = pic.ClientNumber,
CompanyName = client.CompanyNameFull,
AICGroupID = pic.AICStaffGroupID,
RPStaffID = pic.RPStaffID,
MPStaffID = pic.MPStaffID,
CSPStaffID = pic.CSPStaffID,
EQCRStaffID = pic.EQCRStaffID
}).ToList();
//ToList<PicList>() is fine but redundant: the generic type argument is inferred.
you are creating an anonymous type here, which can't be casted like you've tried.
try something like:
var returnList = (from PersonsInChargeEntity pic in picList
join ClientEntity client in clientList
on pic.ClientNumber equals client.ClientNumber
select new PicList
{
ClientNumber = pic.ClientNumber,
CompanyName = pic.CompanyNameFull,
AICGroupID = pic.AICStaffGroupID,
RPStaffID = pic.RPStaffID,
MPStaffID = pic.MPStaffID,
CSPStaffID = pic.CSPStaffID,
EQCRStaffID = pic.EQCRStaffID
})/*.ToList()*/;
personList = picp.GetPersonsInChargeList(); // got 6000++ records
clientList = (List<ClientEntity>)cp.GetClientList(); // got 5000 ++ records after step thru
//PicList sdf;
var returnList = (from PersonsInChargeEntity pic in personList
join ClientEntity client in clientList
on pic.ClientNumber equals client.ClientNumber
select new PicList { ClientNumber = pic.ClientNumber, CompanyName = client.CompanyNameFull, AICGroupID = pic.AICStaffGroupID, RPStaffID = pic.RPStaffID,
MPStaffID = pic.MPStaffID, CSPStaffID = pic.CSPStaffID, EQCRStaffID = pic.EQCRStaffID }).ToList();
but returnList doesnt have any records.
Hmmm, You can do it by very basic method linke this
List<ClientEntity> clientList = new List<ClientEntity>();
var returnList = (from PersonsInChargeEntity pic in picList
join ClientEntity client in clientList
on pic.ClientNumber equals client.ClientNumber
select pic ;
foreach(var item in pic)
{
ClientEntity obj = new ClientEntity();
obj.ClientNumber = item.ClientNumber
......
......
clientList.add(obj);
}
return clientlist;
I hope this will run for you as well

Categories