I'm trying to run a query that gets all of my references, but it isn't working.
What I have right now is
from UserGroups
where Id="ActionGroup"
select Accomplishments.ID, Accomplishments.Accomplish
But I need only the Accomplishments.Accomplish that belong in my other collection ActivityAccomplishments and these are nested in another object.
To be exact, I'm trying to figure out how to query the UserGroups collection and only look at the one with id="ActionGroup". After that I need all of the Accomplishments.Accomplish strings within the UserGroup list to be filtered out if they don't match a id in ActivityAccomplishment.
Basically, in the UserGroup I'm looking at it's List Accomplishments needs to filter out all strings within the Acc class that don't match an Id in ActivityAccomplishments. Can someone please help me.
Here are the classes I'm using.
public class UserGroups
{
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<Acc> Accomplishments { get; set; }
}
public class Acc
{
public string Id { get; set; }
public List<string> Accomplish { get; set; }
}
public class ActivityAccomplishments
{
public string Id { get; set; }
}
try this:
from UserGroups
where Id = "ActionGroup" AND Accomplishments[].Accomplish != "theIdYouDontWant"
select Accomplishments[].Accomplish as AccomplishStringsList
(not necessary to add the 'as AccomplishStringsList' - it is just a name for the results)
Related
I have two SQL tables, User and UserType joined with UserType as a foreign key, with their respective models in ASP. To my understanding, this should be a 1:1 relationship (correct me if I'm wrong). One unique user, set as a type of user (being admin, super admin, user etc).
When I try and retrieve a list of users, it returns a null on the property UserType.
I used Google to get this far, but I'm struggling to get this particular issue fixed.
At one point I got an error stating: "Unable to determine the principal end of an association". To get around that, I included a Required annotation (didn't work) and a ForeignKey annotation (didn't work either) in both models, both simultaneously and separately.
This is what I have so far.
[Table("Users", Schema = "dbo")]
public class Users
{
[Key, ForeignKey("UserType")]
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string ContactNumber { get; set; }
public UserType UserType { get; set; }
public string IsActive { get; set; }
}
[Table("UserType", Schema = "dbo")]
public class UserType
{
[Key]
public Guid Id { get; set; }
public string Type { get; set; }
public string Description { get; set; }
public string IsActive { get; set; }
public Users Users { get; set; }
}
I'm using the below LINQ method to retrieve the data:
public PagedTables<Users> GetAllUsers(Pagination pagination)
{
using (var db = new DbContext())
{
var user = new PagedTables<Users>()
{
Data = db.Users.OrderBy(U => U.Id).Skip(pagination.Page).Take(pagination.Limit).ToList(),
Count = db.Users.Count()
};
return user;
}
}
A break point on the users var shows that the property UserType returns null. I would expect the assigned user type to be joined onto the user.
Any help would be appreciated. Thanks
My EF background is database-first but if you are eager loading (i.e. not lazy loading) then are you missing an Include to tell LINQ to go and get the UserType? Something like;
Data = db.Users.OrderBy(U => U.Id).Skip(pagination.Page).Take(pagination.Limit).Include(U => U.UserType).ToList(),
I want first to say sorry, because I'm new to this programming language, so forgive me if I say or do something wrong.
I created a project with 3 class libraries (1 of them contains the tables from sql server). I made a ViewModel based on the tutorial from: "http://tutlane.com/tutorial/aspnet-mvc/how-to-use-viewmodel-in-asp-net-mvc-with-example", and now I want to be able to update the data in those tables, but I don't know how. I tried to do something but it failed.
`namespace BOL2.ViewModel
{
public class NIRIO
{
[Key]
public int ID { get; set; }
public int Number { get; set; }
public Nullable Date { get; set; }
public int NirID { get; set; }
[DisplayName("TypeID")]
public int TipID { get; set; }
public int SupplierID { get; set; }
public int ProductID { get; set; }
public Nullable<System.DateTime> EntryDate { get; set; }
public Nullable<System.DateTime> ExitDate { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
public decimal Total { get; set; }
public BOL2.tbl_NIR tbnir;
public BOL2.tbl_I_O tblio { get; set; }`
This is my ViewModel. It contains data from those 2 tables (tbl_NIR, first 3, and the others from tbl_I_O. I saw something on my research that they had a repository class, but I don't now if I should do another class for the viewmodel or I sould use the 2 that I already have? Any help is greatly appreciated.
You could do something similar to this.
public void UpdateCar(CarViewModel viewModel)
{
using (DataContext context = new DataContext())
{
CarEntity dataModel = context.CarEntities.where(x => x.Id == viewModel.Id).First();
dataModel.Name = viewModel.Name;
dataModel.Type = viewModel.Type;
context.SaveChanges();
}
}
You need to create your model objects from your view model and set the values for the models.
I'm not quite sure what is the method you used and didn't work. Just in case you tried to update the tables through the view, then you cannot do that. Because you have join
inform IT explanation
I recommend you to create a stored procedure in your database. Then call the procedure trough the code. It's secure and fast. explained here
I'm making a task management tool using AngularJS for the frontend and ASP.NET WEB API 2 for the backend. I have two entities in the database, a "Task" and a "Type". Each task has one type associated. The user fills a form when he can create a new task, and he has to select a type for that task.
Here's the C# code:
// KBTM_Task.cs file
public class KBTM_Task
{
public int ID { get; set; }
public string TaskID { get; set; } // User defined ID
public string Title { get; set; }
public string Description { get; set; }
}
// KBTM_Type.cs file
public class KBTM_Type
{
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
So my question is: how do I "connect" the two in the database? What I mean is, let's say I want to POST data to the database. I have to make two POSTs, right? One for the Task and one for the Type, since they're two separate entities.
But since they're stored with two different IDs, how do I know that a certain task has a certain type? In other words, if I send a GET request to KBTM_Task, how do I get the type of that task?
Modify your KBTM_Task entity to include the Type Id and foreign key relationship
public class KBTM_Task
{
public int ID { get; set; }
public string TaskID { get; set; } // User defined ID
public string Title { get; set; }
public string Description { get; set; }
public int TypeID { get; set; }
[ForeignKey("TypeID")]
public virtual KBTM_Type Type { get; set; }
}
This way when you get the data from the API your task object will already include the key ("TypeID") that can be updated and related object ("Type") that you can access its properties (Name, Description, ...).
When you update TypeID on the client object (model) you can simply push the updated task object to the API using $http.put() to handle the database update.
1) Add foreign key using fluent api (or data annotation)
// KBTM_Task.cs file
public class KBTM_Task
{
public int ID { get; set; }
public string TaskID { get; set; } // User defined ID
public string Title { get; set; }
public string Description { get; set; }
public int KBTM_TypeID {get;set}
public virtual KBTM_Type {get; set}
}
// KBTM_Type.cs file
public class KBTM_Type
{
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public KBTM_Task KBTM_Task { get; set;}
}
Add the following in the class inheriting from DbContext
public class KbtmContext : DbContext
{
...
//public virtual DbSet<KBTM_Task> KbtmTasks {get; set;}
...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Configure KBTM_TypeID as FK for KBTM_Task
modelBuilder.Entity<KBTM_Task>()
.HasRequired(k => k.KBTM_Type)
.WithRequiredPrincipal(ad => ad.KBTM_Task);
}
}
2) If exposing the entity class in API response or request then you need to exclude navigation property from being serialized.
// KBTM_Task.cs file
public class KBTM_Task
{
...
[JsonIgnore]
public virtual KBTM_Type Type { get; set; }
}
To use the [JsonIgnore] atttribute use Install-Package Newtonsoft.Json in package manager console.(One of the popular solutions to manage serialization)
in my Winform Application, I have Suppliers, Customers, Transport Companies. They are similar as they are basically some kind of Contacts, however they do different slightly in term of available fields.
For example Suppliers need have StartDate and EndDate fields. And currently even though Suppliers and Customers could have more than one contact person\entity, but we are not going do that in these release, but the Transport companies will have more than one contact person\entity and addresses. At the same time, the Supplier and Customer do require PO Address and Delivery Address, and two phone numbers just in case.
Currently in my Code First Entities, I have Suppliers, Customers and Transport Companies each contains a PrimaryContact which is a Contact Type, and for each Contact type, I have a ICollection of Address and Phone which in turn store one or more than one address and phone information. The difference is that Transport Companies will have a collection of Contact in addition of PrimaryContact.
As my understanding, even I have the freedom of design the DB/Entity by myself, there is not always the case that Objects in BLL is exactly mapping of the DB structure underneath.
So the idea is in my BLL layer, I will translate the data from Supplier to BOSupplier to Presentation Layer, and will doing translation to Supplier when get data back from Presentation Layer to DAL. Because in my Presentation Layer, the Supplier will looks like:
public class BOSupplier
{
// Primery key
public int ID { get; set; }
public string Name { get; set; }
public string TaxNumber { get; set; }
public bool InActive { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public string BankAccountNumber { get; set; }
public string BankAccountName { get; set; }
// Property related to Contact Table
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public string SkypeName { get; set; }
// Proterty related to Address Table
// PO address Info
public string POAddressLine { get; set; }
public string POCity { get; set; }
public string PORegion { get; set; }
public string POCountry { get; set; }
public string POPostCode { get; set; }
// Delivery AddressLine
public string DelAddressLine { get; set; }
public string DelCity { get; set; }
public string DelRegion { get; set; }
public string DelCountry { get; set; }
public string DelPostCode { get; set; }
// Proterties related to Phone table
public string PhoneNumber1 { get; set; }
public string PhoneNumber2 { get; set; }
}
}
But in my DAL Layer, my Supplier will looks like this:
public class Supplier
{
// Primery key
public int ID { get; set; }
public string Name { get; set; }
public virtual Contact PrimaryContact { get; set; }
public string TaxNumber { get; set; }
public bool InActive { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public string BankAccountNumber { get; set; }
public string BankAccountName { get; set; }
}
Then when I am actually writing code for BLL classes to manage my intermediate BOSupplier object and List which didn't actually mapping back an Entity to DB side. It seems a lots low level code just to transfer/map fields from two slightly different BOSupplier and Supplier, like this:
public static IEnumerable<BOSupplier> GetBOSuppliers()
{
var suppliers = dbContext.Suppliers;
BOSupplier currentSupplier;
foreach (Supplier supplier in suppliers)
{
currentSupplier = new BOSupplier()
{
ID = supplier.ID,
Name = supplier.Name,
Code = supplier.Code,
FirstName = supplier.PrimaryContact.FirstName,
TaxNumber = supplier.TaxNumber
};
// PO Address
Address poAddress = supplier.PrimaryContact.Addresses
.FirstOrDefault<Address>(a => a.AddressTypeValue == (int)AddressTypes.Postal);
if (poAddress != null)
{
currentSupplier.POAddressLine = poAddress.AddressLine1;
currentSupplier.POCity = poAddress.City;
currentSupplier.POCountry = poAddress.Country;
}
// Delivery Address
Address delAddress = supplier.PrimaryContact.Addresses
.FirstOrDefault<Address>(a => a.AddressTypeValue == (int)AddressTypes.Delivery);
if (delAddress != null)
{
currentSupplier.DelAddressLine = delAddress.AddressLine1;
currentSupplier.DelCity = delAddress.City;
currentSupplier.DelCountry = delAddress.Country;
}
// ToDo:
// There is probably more to think about how we want map multi phone numbers into limited two phone numbers
if (supplier.PrimaryContact.Phones.Count > 0)
{
foreach (Phone phone in supplier.PrimaryContact.Phones)
{
if (phone.PhoneType == PhoneTypes.Default)
{
currentSupplier.PhoneNumber1 = phone.PhoneNumber;
}
else
{
currentSupplier.PhoneNumber2 = phone.PhoneNumber;
}
}
}
this.boSupplierList.Add(currentSupplier);
}
return boSupplierList;
}
I am keep thinking: "Maybe my Entity Model should be simpler, or there is some better way of doing what I am trying to?". So please, from your experience, tell me that my Entity model are on over-complex side, or I just need some better way of mapping from BOSuppier to Supplier or some other thoughts.
Your entity model is not complex according to your description of the domain. You can use AutoMapper to map your Supplier to BOSupplier. Here is an example of flattening object graph using AutoMapper.
I see a problem in your GetBOSuppliers(). It uses lazy loading when you access PrimaryContact and Addresses. To avoid the multiple round trips to database you can eager load them as follows.
var suppliers = dbContext.Suppliers.Include(s => s.PrimaryContact.Addresses);
This is probably just because my knowledge with the EF Code First fluent API is lacking, but I'm stumped.
I want to model the following:
A Groups collection with Id and Name
A Users collection with Id and Name
Each user is assigned to exactly one primary group
Each user may have zero or many secondary groups
The table structure I'm going for would look like:
Groups
Id
Name
Users
Id
Name
PrimaryGroupId
SecondaryGroupAssignments
UserId
GroupId
I've been beating my head against a wall trying to model this with EF Code First, but I can't get it to accept both relationships between User and Group. Sorry for not posting any .NET code (I'm happy to), but it's probably all wrong anyway.
Is there a way to make EF model this? I'm assuming I have to do some sort of configuration with the Fluent API. Maybe a better question is: is there any good, definitive reference for the Fluent API?
Thanks!
Try this (untested):
public class Group
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<User> PrimaryUsers { get; set; }
public virtual ICollection<User> SecondaryUsers { get; set; }
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int PrimaryGroupId { get; set; }
public virtual Group PrimaryGroup { get; set; }
public virtual ICollection<Group> SecondaryGroups { get; set; }
}
public class Context : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Group> Groups { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>()
.HasRequired(u => u.PrimaryGroup)
.WithMany(g => g.PrimaryUsers)
.HasForeignKey(u => u.PrimaryGroupId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<User>()
.HasMany(u => u.SecondaryGroups)
.WithMany(g => g.SecondaryUsers)
.Map(m => m.MapLeftKey("UserId")
.MapRightKey("GroupId")
.ToTable("SecondaryGroupAssignments"));
}
}
Based on Ladislav's excellent answer, here's how to do it without using any mappings - just attributes applied to the Model classes themselves:
public class Group
{
public int Id { get; set; }
[MaxLength(300)]
public string Name { get; set; }
public ICollection<User> Users { get; set; }
}
public class User
{
public int Id { get; set; }
[MaxLength(300)]
public string Name { get; set; }
[ForeignKey("PrimaryGroup")]
public int PrimaryGroupId { get; set; }
[Required]
public Group PrimaryGroup { get; set; }
[InverseProperty("Users")]
public ICollection<Group> SecondaryGroups { get; set; }
}
Notes
If you want, you can add the virtual keyword to the 2 ICollections and the Group. This allows lazy-loading. Performance-wise, I don't recommend it, but it is possible.
I included MaxLength attributes with an arbitrary (but safe) length of 300, because putting strings out in EF without a MaxLength gets you low-performance NVarChar(MAX) columns. Totally irrelevant to what's being asked but better to post good code.
I recommend against class names "User" and "Group" for your EF classes. They're going to complicate any SQL you attempt to run later, having to type [User] and [Group] to access them, and complicate using these classes in MVC Controllers where your class User will conflict with the Context property User that gives you access to the Asp.Net Identity library.