Inline comparison works, but if I wrap that in a method, LINQ expression cannot be translated - entity-framework-core

Full source code is at the bottom, but here is the highlight.
//Works
if (mydb.Articles.Any(x => (x.ArticleId == demo.ArticleId && x.Title == demo.Title)))
public bool IsSame(WebArticle other)
{
return (ArticleId == other.ArticleId && Title == other.Title);
}
//Doesn't work
if (mydb.Articles.Any(x => x.IsSame(demo)))
Is there any way to avoid the repeated code of x.ArticleId == demo.ArticleId && x.Title == demo.Title and reuse one source?
Program.cs
using Microsoft.EntityFrameworkCore.Storage;
using System.Diagnostics;
namespace EntityTest
{
internal class Program
{
static void Main(string[] args)
{
var mydb = new MyDbContext();
var article1 = new Article()
{
ArticleId = 1234,
Title = "First",
};
var article2 = new Article()
{
ArticleId = 5678,
Title = "Second",
};
var article3 = new Article()
{
ArticleId = 9012,
Title = "Third",
};
mydb.Articles.AddRange(article1, article2, article3);
mydb.SaveChanges();
var demo = new WebArticle()
{
ArticleId = 5678,
Title = "Second",
};
//use inline code
if (mydb.Articles.Any(x => (x.ArticleId == demo.ArticleId && x.Title == demo.Title)))
{
Console.WriteLine("Exists");
}
else
{
Console.WriteLine("Doesn't exist");
}
//use method
if (mydb.Articles.Any(x => x.IsSame(demo)))
{
Console.WriteLine("Exists");
}
else
{
Console.WriteLine("Doesn't exist");
}
}
}
class WebArticle
{
public int ArticleId { get; set; }
public string Title { get; set; }
}
}
MyDbContext.cs
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EntityTest
{
internal class MyDbContext:DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseInMemoryDatabase("memory");
base.OnConfiguring(optionsBuilder);
}
public DbSet<Article> Articles { get; set; }
public DbSet<ArticleImage> ArticleImages { get; set; }
}
class Article
{
[Key]
public int Id { get; set; }
public int ArticleId { get; set; }
public string Title { get; set; }
public bool IsSame(WebArticle other)
{
return (ArticleId == other.ArticleId && Title == other.Title);
}
}
class ArticleImage
{
public int Id { get; set; }
public int ArticleId { get; set; }
public string Url { get; set; }
}
}

Changed the code like the following. It worked without using a third-party library.
Program.cs
//use method
//if (mydb.Articles.AsExpandable().Any(x => x.IsSame(demo)))
if (mydb.Articles.Any(Article.IsSame(demo)))
{
Console.WriteLine("Exists");
}
else
{
Console.WriteLine("Doesn't exist");
}
MyDbContext.cs
class Article
{
[Key]
public int Id { get; set; }
public int ArticleId { get; set; }
public string Title { get; set; }
//public bool IsSame(WebArticle other)
//{
// return (ArticleId == other.ArticleId) && (Title == other.Title);
//}
public static Expression<Func<Article, bool>> IsSame(WebArticle other)
{
return current => (current.ArticleId == other.ArticleId) && (current.Title == other.Title);
}

Related

How to insert payload data in many-to-many relationships with EF Core 5

I have this relationship between Licitadores and Ofertas
public class Licitador
{
public int Id { get; set; }
public string Nombre { get; set; }
[StringLength(maximumLength: 15)]
public string CodigoSAP { get; set; }
public List<Oferta> Ofertas { get; set; } = new List<Oferta>();
}
public class Oferta
{
[StringLength(maximumLength:6)]
public string Id { get; set; }
[StringLength(maximumLength: 5)]
public string IdPresentada { get; set; }
....
public List<Licitador> Licitadores { get; set; } = new List<Licitador>();
}
And the join table in the context
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<LicitacionesEnSolitario>().ToTable("LicitacionesSolitario");
modelBuilder.Entity<Licitador>()
.HasMany(o => o.Ofertas)
.WithMany(of => of.Licitadores)
.UsingEntity<LicitacionesEnSolitario>
(oo => oo.HasOne<Oferta>().WithMany(),
oo => oo.HasOne<Licitador>().WithMany())
.Property(oo => oo.Adjudicado)
.IsRequired();
}
I need this data in my entity/table LicitacionesEnSolitario in addition to PK y FK
public class LicitacionesEnSolitario
{
public int LicitadorId { get; set; }
public string OfertaId { get; set; }
public bool Adjudicado { get; set; }
public string Plazo { get; set; }
public decimal PresupuestoOfertado { get; set; }
public DateTime? FechaAdjudicacion { get; set; }
}
Here I insert the data importing them from another database
public int ImportarLicitacionesEnSolitario()
{
try
{
int registrosAñadidos = 0;
var registrosSAP = _contextSAP.LicitacionesEnSolitario
.FromSqlRaw("sql")
.ToList();
foreach (var registroSAP in registrosSAP)
{
var oferta = _contextBoletus.Ofertas.Find(registroSAP.OfertaId);
var licitador = _contextBoletus.Licitadores.Where(l => l.CodigoSAP == registroSAP.CodigoSAP).FirstOrDefault();
oferta.Licitadores.Add(licitador);
registrosAñadidos +=1;
}
_contextBoletus.SaveChanges();
return registrosAñadidos;
}
catch (Exception ex)
{
throw ex;
}
}
This works fine and insert data in "LicitacionesEnSolitario" but with this fields Adjudicado, Plazo, PresupuestoPfertado y FechaAdjudicacion with nulls.
I don't know how to insert them at the time I insert Licitadores and if I try to update after the Add method using the PKs I just added
foreach (var registroSAP in registrosSAP)
{
var oferta = _contextBoletus.Ofertas.Find(registroSAP.OfertaId);
var licitador = _contextBoletus.Licitadores.Where(l => l.CodigoSAP == registroSAP.CodigoSAP).FirstOrDefault();
oferta.Licitadores.Add(licitador);
var ls = _contextBoletus.Set<LicitacionesEnSolitario>()
.SingleOrDefault(ls => ls.OfertaId == oferta.Id & ls.LicitadorId == licitador.Id);
ls.Adjudicado = registroSAP.Adjudicado;
ls.PresupuestoOfertado = registroSAP.PresupuestoOfertado;
ls.FechaAdjudicacion = registroSAP.FechaAdjudicacion;
registrosAñadidos +=1;
}
_contextBoletus.SaveChanges();
return registrosAñadidos;
I get this error System.NullReferenceException: Object reference not set to an instance of an object.
Any idea, please?
Thanks
This is the best way I found
foreach (var registroSAP in registrosSAP)
{
var oferta = _contextBoletus.Ofertas.Find(registroSAP.OfertaId);
var licitador = _contextBoletus.Licitadores.Where(l => l.CodigoSAP == registroSAP.CodigoSAP).FirstOrDefault();
var ls = _contextBoletus.Set<LicitacionesEnSolitario>().Add(
new LicitacionesEnSolitario
{
LicitadorId = licitador.Id,
OfertaId = oferta.Id,
Adjudicado = registroSAP.Adjudicado,
Plazo = registroSAP.Plazo,
PresupuestoOfertado = registroSAP.PresupuestoOfertado,
FechaAdjudicacion = registroSAP.FechaAdjudicacion
});
registrosAñadidos += 1;
}
Thanks

AutoMapper with EF Core doesn't return OData #count correctly if using $top

I'm using the solution provided by this link: AutoMapper don't work with entity EF Core
My problem is when using $top, #odata.count always return the number informed in $top but should return the number of total record.
I know that ODataQueryOptions has a property “Count”, but I don't know if it's possible to use to solve the problem
I'm using the below the code provided by Дмитрий Краснов in his question including the solution by Ivan Stoev:
There is entities:
public class LessonCatalog {
public string Name { get; set; }
public int? ImageId { get; set; }
public virtual Image Image { get; set; }
public virtual ICollection<Lesson> Lessons { get; set; }
}
public class Lesson {
public string Name { get; set; }
public string Description { get; set; }
public int? ImageId { get; set; }
public virtual Image Image { get; set; }
public int LessonCatalogId { get; set; }
public virtual LessonCatalog LessonCatalog { get; set; }
}
Views:
public class LessonView {
public string Name { get; set; }
public string Description { get; set; }
public int? ImageId { get; set; }
public ImageView Image { get; set; }
public int LessonCatalogId { get; set; }
public LessonCatalogView LessonCatalog { get; set; }
}
public class LessonCatalogView {
public string Name { get; set; }
public int? ImageId { get; set; }
public ImageView Image { get; set; }
public IEnumerable<LessonView> Lessons { get; set; }
}
My maps:
CreateMap<LessonCatalog, LessonCatalogView>()
.ForMember(dest => dest.Image, map => map.ExplicitExpansion())
.ForMember(dest => dest.Lessons, map => map.ExplicitExpansion());
CreateMap<Lesson, LessonView>()
.ForMember(dest => dest.LessonCatalog, map => map.ExplicitExpansion());
In my repository:
protected readonly DbContext _context;
protected readonly DbSet<TEntity> _entities;
public Repository(DbContext context) {
_context = context;
_entities = context.Set<TEntity>();
}
public IEnumerable<TView> GetOData<TView>(ODataQueryOptions<TView> query,
Expression<Func<TEntity, bool>> predicate = null) {
IQueryable<TEntity> repQuery = _entities.AsQueryable();
IQueryable res;
if (predicate != null) repQuery = _entities.Where(predicate);
if (query != null) {
string[] expandProperties = GetExpands(query);
//!!!
res = repQuery.ProjectTo<TView>(Mapper.Configuration, null, expandProperties);
//!!!
var settings = new ODataQuerySettings();
var ofilter = query.Filter;
var orderBy = query.OrderBy;
var skip = query.Skip;
var top = query.Top;
if (ofilter != null) res = ofilter.ApplyTo(res, settings);
if (orderBy != null) res = orderBy.ApplyTo(res, settings);
if (skip != null) res = skip.ApplyTo(res, settings);
if (top != null) res = top.ApplyTo(res, settings);
} else {
res = repQuery.ProjectTo<TView>(Mapper.Configuration);
}
return (res as IQueryable<TView>).AsEnumerable();
}
If my query result has 1007 records, and I use
…$count=true&$top=5
the result for count should be
"#odata.count": 1007
But instead the result is always
"#odata.count": 5
Using SQL Server Profile I can see that the Select for count is including the “top”. So, how to avoid this to happen?
I received a help from the Github Guy (thanks to #Gennady Pundikov) and could now answer this question.
I changed the GetOData Method to get the Count before apply others settings:
public IEnumerable<TView> GetOData<TView>(ODataQueryOptions<TView> query,
Expression<Func<TEntity, bool>> predicate = null) {
IQueryable<TEntity> repQuery = _entities.AsQueryable();
IQueryable res;
if (predicate != null) repQuery = _entities.Where(predicate);
if (query != null) {
string[] expandProperties = GetExpands(query);
//!!!
res = repQuery.ProjectTo<TView>(Mapper.Configuration, null, expandProperties);
//!!!
var settings = new ODataQuerySettings();
var ofilter = query.Filter;
var orderBy = query.OrderBy;
var skip = query.Skip;
var top = query.Top;
if (ofilter != null) res = ofilter.ApplyTo(res, settings);
if (query.Count?.Value == true)
{
// We should calculate TotalCount only with filter
// http://docs.oasis-open.org/odata/odata/v4.0/odata-v4.0-part2-url-conventions.html#_Toc371341773
// 4.8 Addressing the Count of a Collection
// "The returned count MUST NOT be affected by $top, $skip, $orderby, or $expand.
query.Request.ODataFeature().TotalCount = ((IQueryable<TView>)res).LongCount();
}
if (top != null) res = top.ApplyTo(res, settings);
if (orderBy != null) res = orderBy.ApplyTo(res, settings);
if (skip != null) res = skip.ApplyTo(res, settings);
} else {
res = repQuery.ProjectTo<TView>(Mapper.Configuration);
}
return (res as IQueryable<TView>).AsEnumerable();
}

Generic Repository EF 5 - Update Entity And It's Complex/Scalar/Navigation Properties

I'm trying to find an easy solution for updating an entity + the included properties in my solution. I've created an Generic Repository for my DBContext (database). It does update the parent entity, but not handling changes on the child properties. Is there a way to handle or track those changes?
Example code for updating child propery: (look at comment - example code)
[HttpPut]
public HttpResponseMessage PutBrand(Brand brand)
{
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
try
{
// example code
brand.BrandSizes.FirstOrDefault().Name = "I'm a Test";
// add values
brand.State = State.Changed;
brand.DateChanged = DateTime.Now;
// update
brand = _brandService.UpdateBrand(brand);
// save
_brandService.SaveBrandChanges();
// signalR
Hub.Clients.All.UpdateBrand(brand);
return Request.CreateResponse<Brand>(HttpStatusCode.OK, brand);
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
}
}
Context:
public class ERPContext : DbContext
{
#region Catalog
public DbSet<Brand> Brands { get; set; }
public DbSet<BrandSize> BrandSizes { get; set; }
public DbSet<BrandSizeOption> BrandSizeOptions { get; set; }
public DbSet<BrandTierPrice> BrandTierPrices { get; set; }
#endregion Catalog
public ERPContext()
: base("db-erp")
{
Configuration.LazyLoadingEnabled = false;
Configuration.ProxyCreationEnabled = false;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Generic Repository:
public class ERPRepository<T> : IRepository<T> where T : class
{
#region Fields
private DbSet<T> _dbSet;
private DbContext _dataContext;
#endregion Fields
#region Ctor
public ERPRepository(DbContext dataContext)
{
if (dataContext == null)
{
throw new ArgumentNullException("dataContext", "dataContext cannot be null");
}
_dataContext = dataContext;
_dbSet = _dataContext.Set<T>();
}
#endregion Ctor
#region Methods
public T Add(T item)
{
return _dbSet.Add(item);
}
public T Delete(T item)
{
return _dbSet.Remove(item);
}
public T Update(T item)
{
var updated = _dbSet.Attach(item);
_dataContext.Entry(item).State = EntityState.Modified;
return updated;
}
public IQueryable<T> Query(params Expression<Func<T, object>>[] includes)
{
var query = _dbSet;
if (includes != null)
{
includes.ToList().ForEach(x => query.Include(x).Load());
}
return query;
}
public void SaveChanges()
{
_dataContext.SaveChanges();
}
#endregion Methods
}
Model:
public class Brand
{
#region Ctr
public Brand()
{
BrandSizes = new List<BrandSize>();
BrandTierPrices = new List<BrandTierPrice>();
}
#endregion Ctr
#region Properties
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int? LogoId { get; set; }
public int DisplayOrder { get; set; }
public bool Deleted { get; set; }
public bool Locked { get; set; }
public State State { get; set; }
public DateTime DateChanged { get; set; }
public DateTime DateCreated { get; set; }
#endregion Properties
#region Mapping
public virtual Picture Logo { get; set; }
public virtual List<BrandSize> BrandSizes { get; set; }
public virtual List<BrandTierPrice> BrandTierPrices { get; set; }
#endregion Mapping
}
BrandService:
public partial class BrandService : IBrandService
{
#region Fields
private readonly IRepository<Brand> _brandRepository;
private readonly IRepository<BrandSize> _brandSizeRepository;
private readonly IRepository<BrandSizeOption> _brandSizeOptionRepository;
#endregion Fields
#region Ctor
public BrandService(IRepository<Brand> brandRepository, IRepository<BrandSize> brandSizeRepository, IRepository<BrandSizeOption> brandSizeOptionRepository)
{
_brandRepository = brandRepository;
_brandSizeRepository = brandSizeRepository;
_brandSizeOptionRepository = brandSizeOptionRepository;
}
#endregion Ctor
#region Methods
public virtual IEnumerable<Brand> GetAllBrands()
{
return _brandRepository.Query(x => x.BrandSizes);
//return _brandRepository.Query();
}
public virtual Brand GetBrandById(int id)
{
return _brandRepository.Query().Where(x => x.Id == id).FirstOrDefault();
}
public virtual Brand InsertBrand(Brand brand)
{
return _brandRepository.Add(brand);
}
public virtual Brand UpdateBrand(Brand brand)
{
return _brandRepository.Update(brand);
}
public virtual Brand DeleteBrand(Brand brand)
{
return _brandRepository.Delete(brand);
}
public virtual void SaveBrandChanges()
{
_brandRepository.SaveChanges();
}
#endregion Methods
}
Create IObjectWithState interface and State enum to track changes manually:
public interface IObjectWithState
{
State State { get; set; }
}
public enum State
{
Added,
Unchanged,
Modified,
Deleted
}
and implement the interface in every mapped entity
public class Brand:IObjectWithState
{ ....
[NotMapped]
public State State { get; set; }}
and add these two helper methods to convert the state and to apply the changes in the entire graph:
public static EntityState ConvertState(State state)
{
switch (state)
{
case State.Added :
return EntityState.Added;
case State.Deleted:
return EntityState.Deleted;
case State.Modified:
return EntityState.Modified;
case State.Unchanged:
return EntityState.Unchanged;
default:
return EntityState.Unchanged;
}
}
public static void ApplyStateChanges(this DbContext context)
{
foreach (var entry in context.ChangeTracker.Entries<IObjectWithState>())
{
IObjectWithState stateInfo = entry.Entity;
entry.State = StateHelpers.ConvertState(stateInfo.State);
}
}
and when update or insert any object edit the state of it like this object.State = State.Modified;
and then modify your insert or update method to be like this:
public void InsertOrUpdate(T entity, bool IsGraph)
{
if (((IObjectWithState)entity).State == State.Added)
{
dataContext.Entry(entity).State = System.Data.Entity.EntityState.Added;
}
else
{
dbset.Add(entity);
dataContext.Entry(entity).State = System.Data.Entity.EntityState.Modified;
}
//This method change the state of every changed object
if (IsGraph)
ApplyStateChanges(dataContext);
dataContext.Commit();
}

How to write an Edit Action

I am trying to come up with an edit action. See below for what i have so far.
ViewModel:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace GlobalUnitedSC.WebUI.Models
{
public sealed class CreateMensPlayerViewModel
{
//Player profile starts here
[HiddenInput(DisplayValue=false)]
public int MensTeamId { get; set; }
[HiddenInput(DisplayValue = false)]
public int PlayerId { get; set; }
[Required]
public string Name { get; set; }
[DataType(DataType.Date)]
public DateTime? BirthDate { get; set; }
[Required]
public string Position { get; set; }
public int ShirtNumber { get; set; }
[DataType(DataType.Date)]
public DateTime? Joined { get; set; }
public string Country { get; set; }
[DataType(DataType.MultilineText)]
public string Description { get; set; }
public byte[] ImageData { get; set; }
[HiddenInput(DisplayValue = false)]
public string ImageMimeType { get; set; }
[DataType(DataType.EmailAddress)]
public string EmailAddress { get; set; }
[DataType(DataType.PhoneNumber)]
public string PhoneNumber { get; set; }
//Player Statistics starts here
public int Games { get; set; }
public int Goals { get; set; }
public int Assists { get; set; }
public int TotalShots { get; set; }
public int ShotsOnGoal { get; set; }
public int FoulsDrawn { get; set; }
public int FoulsCommitted { get; set; }
public int Saves { get; set; }
public int BlueCards { get; set; }
public int YellowCards { get; set; }
public int RedCards { get; set; }
}
}
Create Actions:
[HttpGet]
public ActionResult Create(int mensTeamId)
{
new CreateMensPlayerViewModel {MensTeamId = mensTeamId};
return View();
}
[HttpPost]
public ActionResult Create(CreateMensPlayerViewModel viewModel, HttpPostedFileBase image)
{
if (ModelState.IsValid)
{
var mensTeam = _dataSource.MensTeams.Single(t => t.Id == viewModel.MensTeamId);
var mensPlayer = new MensPlayer
{
Name = viewModel.Name,
BirthDate = viewModel.BirthDate,
Position = viewModel.Position,
ShirtNumber = viewModel.ShirtNumber,
Joined = viewModel.Joined,
Country = viewModel.Country,
Description = viewModel.Description,
EmailAddress = viewModel.EmailAddress,
PhoneNumber = viewModel.PhoneNumber,
Games = viewModel.Games,
Goals = viewModel.Goals,
Assists = viewModel.Assists,
TotalShots = viewModel.TotalShots,
ShotsOnGoal = viewModel.ShotsOnGoal,
FoulsDrawn = viewModel.FoulsDrawn,
FoulsCommitted = viewModel.FoulsCommitted,
Saves = viewModel.Saves,
BlueCards = viewModel.BlueCards,
YellowCards = viewModel.YellowCards,
RedCards = viewModel.RedCards
};
mensTeam.MensPlayers.Add(mensPlayer);
_dataSource.Save();
TempData["message"] = string.Format("{0} has been saved", mensPlayer.Name);
return RedirectToAction("detail", "MensTeam", new {id = viewModel.MensTeamId});
}
return View(viewModel);
}
HttpGet Edit Action
[HttpGet]
public ActionResult Edit (int id)
{
var mensPlayer = _dataSource.MensPlayers.FirstOrDefault(p => p.Id == id);
return View(mensPlayer);
}
Now could anyone please help me with the HttpPost Edit action, preferably one based on the model class mentioned above?
I was hoping it has something to do with the line below, if this creates a new player, what could i write to edit that player?
var mensPlayer = new MensPlayer {}
Since it's a post the method is kind of equal to your create-method. You will receive a MensPlayer as a parameter.
Than you check if the Model is valid (validation etc.) and flag the entry as modified and save the changes.
[HttpPost]
public ActionResult Edit(MyModel myModel)
{
if (ModelState.IsValid)
{
DbContext.Entry(myModel).State = EntityState.Modified;
DbContext.SaveChanges();
return RedirectToAction("Index");
}
return View(myModel);
}
DBContext
public class ModelContext : DbContext
{
public DbSet<MyModel> MyModelSet{ get; set; }
}
More info about DBContext.
With help of Slauma in the comments in the repost or extension of this question at:
Repost/Extension
This is what he suggested i do and it works.
Add to IDataSource Interface:
void Update(MensPlayer mensPlayer);
Update Implemented in Db class:
void IDataSource.Update(MensPlayer mensPlayer)
{
Entry(mensPlayer).State = EntityState.Modified;
}
Edit Action:
[HttpPost]
public ActionResult Edit(MensPlayer mensPlayer)
{
if (ModelState.IsValid)
{
//Save Player
_dataSource.Update(mensPlayer);
_dataSource.Save();
TempData["message"] = string.Format("{0} has been saved", mensPlayer.Name);
return RedirectToAction("Detail", "MensPlayer", new {id = mensPlayer.Id});
}
return View(mensPlayer);
}
And Just like that all works fine, although i was under the assumption that i would implement Update to the whole DbSet like i did with Save.

Update list object based on other LINQ / LAMBDA

Here are my two objects
public class ObjectHeaderBuffer
{
public int DataObjectId { get; set; }
public string FileName { get; set; }
public int RowCount { get; set; }
public string Checksum { get; set; }
public int ReconTarget { get; set; }
}
public class ObjectHeaderAttribute
{
public int DataObjectId { get; set; }
public int AttributeType { get; set; }
public int AttributeValue { get; set; }
}
var ohBuffer = new List<ObjectHeaderBuffer>();
var ohAttribute = new List<ObjectHeaderAttribute>();
I want to update ohBuffer.ReconTarget with ohAttribute.AttributeValue where ohBuffer.DataObjectId == ohAttribute.DataObjectId
what is linq or lambda of this?
You need to iterate each item in ohBuffer and look up the value in ohAttribute.
Assuming there is only one Attribute for each Buffer, this will work.
ohBuffer.ForEach(b => b.ReconTarget = ohAttribute
.SingleOrDefault(a => a.DataObjectId == b.DataObjectId).AttributeValue);
If the lookup returns null, you can either coalesce to a new object and take the default value
ohBuffer.ForEach(b => b.ReconTarget =
(ohAttribute.SingleOrDefault(a => a.DataObjectId == b.DataObjectId)
?? new ObjectHeaderAttribute())
.AttributeValue);
or you could just take null
ohBuffer.ForEach(b => b.ReconTarget =
{
var attribute = ohAttribute
.SingleOrDefault(a => a.DataObjectId == b.DataObjectId);
if (attribute == null)
return null;
return attribute.AttributeValue;
});
They way i did is:
foreach (var objectHeaderBuffer in ohBuffer)
{
var objectHeaderAttribute = (from c in ohAttribute where c.DataObjectId == objectHeaderBuffer.DataObjectId select c).First();
objectHeaderBuffer.ReconTarget = objectHeaderAttribute.AttributeValue;
}
If your relation is 1:1 Then
foreach (ObjectHeaderBuffer Itemx in ohBuffer)
{
ObjectHeaderAttribute Itemy= (from ObjectHeaderAttribute c in ohAttribute where c.DataObjectId == Itemx.DataObjectId select c).FirstOrDefault();
if(Itemy!=null)
{
Itemx .ReconTarget = Itemy.AttributeValue;
}
}
Or
foreach (ObjectHeaderBuffer Itemx in ohBuffer)
{
ObjectHeaderAttribute Itemy= ohAttribute.Where(c=>c.DataObjectId == Itemx .DataObjectId).FirstOrDefault();
if(Itemy!=null)
{
Itemx .ReconTarget = Itemy.AttributeValue;
}
}