These are my entities...
Public Class Account
Public Property AccountId As Integer
Public Property AccountDescription As String
Public Property Transactions As List(Of Transaction)
End Class
Public Class Transaction
Public Property TransactionId As Integer
Public Property AccountId As Integer
Public Property TransferAccountId As Integer
Public Property TransactionDescription As String
End Class
I now know I can do this. db.Account.Include("Transactions").SingleOrDefault(Function(a) a.AccountId = myAccountId)
However this only includes the transactions that have AccountId = myAccountId obviously. But in my case i want all transactions, including those that are involved in a transfer. so where AccountId = AccountId or TransferAccountId = myAccountId. How can i load an account and its list of transactions and transfertransactions in one call?
With your model you cannot do that directly because you have only single Transaction property on Account class. This property will point either to accounts with AccountId == Id or TransferAccountId == Id but never to both. If you want to easily load both types you need two navigation properties on your Account type - one for related transaction and one for transfer transaction, after that you will just use Include for both properties:
db.Account.Include("Transactions")
.Inclue("TransferTransactions")
.SingleOrDefault(Function(a) a.AccountId = myAccountId)
If you don't want to add second navigation property you can do it in reverse direction. Query transactions and eager load account. As a last case you can query account and transactions separately.
Related
class Student{
public string Name {get; set;}
public EntityCollection<Info> Infos {get; set;}
}
class Info{
public string Title {get; set;}
public Student Student {get; set;}
}
I have two entities like this. First I will query one student entity
var student = db.Students.FirstOrDefault(s => s.StudentId = 1);
Then I query Info list of this student in a separate query
var infos = from c in db.Info where c.StudentId = 1 and ....
If I loop though infos and add it manual into student.Infos, it will cause insert new row
foreach(info in infos){
student.Infos.Add(info);
}
How to attach list of info into student entity without insert new row into Info table when db.SaveChanges(). Like
student.Infos = infos
EF does the work for you behind the scenes when you use navigation properties. It's not just a data layer to load data singularly but rather it's set up with the relationships between the data and is capable of loading an entire object graph of related data either in one hit (eager loaded) or on-demand (lazy loaded)
Firstly: you can update your Info collections to ICollection<Info> or List<Info>. I opt for List<Info> because I commonly use .AddRange(). Also, mark it as virtual to enable EF proxies and lazy loading.
From there, to access the Infos on a Student you can just use:
var student = db.Students.Include(s => s.Infos).SingleOrDefault(s => s.StudentId = 1);
This will eager-load the Infos for the selected student. No need to load them separately.
If you leave off the .Include(..) then you can still access the Infos (provided the DbContext is still in scope) though this will trigger additional SQL calls to load the Infos. (Lazy loaded)
When loading data to send outside of the scope of the DbContext, such as returned from an API call, or sent to a view, it's recommended to compose a DTO or ViewModel with just the fields that you need from the various entities, then perform a .Select() to populate them, and return the DTOs not the entities. This avoids problems with lazy loading calls after a DbContext has been disposed and unexpected performance issues if lazy loading is triggered due to serialization or the like.
i am working on a CMS solutions for real estate agencies.
so different users/groups will use the same tool.
i created 1 asp.net membership Database where i manage ALL users.
The users are grouped in different roles.( 1 role = 1 agency office)
Then - for every group i have another Database. In this database i manage the real estates and customers of the given office. (These Databases have the same structure.)
Currently i am using the "custom ASP.NET Profile class" where i store the connectionsstring for the specific database. I create this custom profile if the user logs in.
Now i have the problem, if an anonymous user is visiting the page ( there is a public section ) i get connectionstring errors cause there is no "custom profile" where my functions can read the connectionstring
My Custom Profile Class looks like:
Public Class UserProfile
Inherits ProfileBase
Public Shared Function GetUserProfile(username As String) As UserProfile
Return TryCast(Create(username), UserProfile)
End Function
Public Shared Function GetUserProfile() As UserProfile
Return TryCast(Create(Membership.GetUser().UserName), UserProfile)
End Function
<SettingsAllowAnonymous(False)> _
Public Property role() As String
Get
Return TryCast(MyBase.Item("role"), String)
End Get
Set(value As String)
MyBase.Item("role") = value
End Set
End Property
<SettingsAllowAnonymous(False)> _
Public Property UsersCustomConnectionString() As String
Get
Return TryCast(MyBase.Item("UsersCustomConnectionString"), String)
End Get
Set(value As String)
MyBase.Item("UsersCustomConnectionString") = value
End Set
End Property
End Class
Then i can read my connection string like
Dim currentprofile As UserProfile = UserProfile.GetUserProfile()
Dim strcon As String = currentprofile.UsersCustomConnectionString
How could i solve this issue ?
Or should i use another way to solve the "many connection strings" issue ? if yes, how ? (i think session varaiables won't work)
Thanks in advance
This is what we do: put in web.config an entry for each connection string in the
<appSettings>
section like this:
<add key="connection_string_key" value="YourDBServerConnectionString"/>
Then you read the value from your db access class like this:
System.Configuration.ConfigurationManager.AppSettings[connection_string_key]
And if you want to change them dynamically make some factory class where you read them all and return the right connection string based on the role of the current user or if they are logged in or not.
I have 2 different user account type and they both are stored in their respective tables (Members in Member table and Admin in Administrator table). Now i want to create a common function to access user info for any type of user, so i was looking a for generic function but i am stuck with returning respective class, I have create 2 class MemberInfo for normal users and AdminInfo for Admin usersNow if the generic class passed to this function is MemberInfo than it should process normal user details and return MemberInfo class, and if it's admin users, then it should return AdminInfo class.
Here is something what i have tried but unable to achieve my goal.
Public Function GetAllMembers(Of T)(ByVal accountType As AccountType) As List(Of T)
Dim T_ReturnValue As List(Of T)
Dim returnType As Type = GetType(T)
If returnType Is GetType(MemberInfo) Then
Dim _list As New List(Of MemberInfo)
With New OleDbDataAdapter("SELECT ACCOUNT_NO, COUNTRY FROM Member", Globals.DatabaseConnection)
Dim dt As New DataTable
.Fill(dt)
For Each row As DataRow In dt.Rows
Dim memberInfo As New MemberInfo
memberInfo.AccountNo = row("Account_No").ToString
memberInfo.Country = row("Country").ToString
_list.Add(memberInfo)
Next
End With
Return DirectCast(_list, List(Of T))
End If
End Function
Can anyone help me how i can return respective class, for now i wanted to return memberinfo class only.
Two ways:
You can have two overloaded functions that return different classes.
You can declare the function as Object, and return either class.
You can follow these steps.
Create an abstract class say "User" . And then Member and Admin has to extend that base class user. Assuming, both has same set of properties and that is why you have started using T to make it generic. But as you have said both has different DB table store.
If you different methods defined for Member and Admin, you can segregate them by using interface. Say Member can Send Friend request, so you can have an interface ( Say ISendRequest), that will have Send method definition only. And if Admin can Add new member ,then you can have interface say IAddMember, and Admin will implement IAddMember , Member will implement, ISendRequest.
KEY point Now, define an interface say IGetAllUser with method GetAllUser and User class has to implement that, but it will have abstract method GetAllUser. So point here is you have to have to write this one GetAllMembers, instead each derived class will have method to get corresponding List .
Sample code snippet. This can even accommodate the scenario if both Member and Admin has different properties.
But if you have same properties, then you can define a function in Base class, that takes Datatable and just sets required properties, as both member and admin has same properties. So the sole purpose of GetAllUsers implemented in Member and Admin class is to pass required table name to Data Access layer and get DataTable and pass that to function defined in base class to set required properties and build List of User.
public interface IGetAllUsers
{
List<User> GetAllUsers();
}
abstract class User : IGetAllUsers
{
public abstract List<User> GetAllUsers();
}
class Member : User
{
public override List<Member> GetAllUsers()
{
// Assuming there is data access layer, to get details
}
}
class Admin : User
{
public override List<Admin> GetAllUsers()
{
// Get all admin
}
}
Right. Before addressing your specific question, I want to start at the lower level.
In theory, an admin is a user, so at database level this should rather be implemented so that there is a [Users] table that stores all kinds of users including admins. Then you should add another table called [Admins] which links to the [Users] table through an FK and stores all additional fields that relate to admins only. This is called ISA / inheritance relation in RDBMS theory.
At application level, this will translate to two business classes, one for [User] and one for [Admin], where [Admin] will inherit from [User] class. You can then write a function that returns a [User] object. Since [Admin] inherits from [User], polymorphism will allow you to return [Admin] object from the same function. Then your caller can confirm the returned object type either through type checking, or you can store a boolean field in [Users] table called IsAdmin that will be true for administrators.
I'm using Vici Coolstorage in a Windows Forms project to access a SQLite database. In every table in my database there is a field called ID defined as INTEGER PRIMARY KEY, so it is an auto increment field.
I'm trying to retrieve the value of that field after I store the object in the database, but I always get the value 0 instead of the real ID. The Vici Coolstorage documentation states that "if the primary key is defined as an autonumber (identity) field in the database, your can retrieve the generated primary key after the object is saved", but that doesn't seem to be true unless I'm doing something wrong. Please help me. This code will reproduce the problem:
<MapTo("Company")> Public MustInherit Class Company
Inherits CSObject(Of Company, Integer)
Public MustOverride ReadOnly Property ID As Integer
Public MustOverride Property Name As String
End Class
Sub SomeMethod()
Dim C As Company = Company.[New]
C.Name = "Some name"
C.Save()
MessageBox.Show(C.ID) 'This always prints 0!!!
End Sub
Thank you!
Had faced this issue and figured out that setting the identity attribute on the field solved this.
[Identity]
public int Id
{
get { return (int)GetField("Id"); }
}
I am facing an issue when validating object which has more than one relationship to bean of particular type but each of relationship must be validated in a different manner.
Composite class:
public class Composite{
#Valid
private Person insurer;
#Valid
private Person insured;
...(other properties)
private String foo;
}
Person class:
public class Person{
#NotNull(groups={Insurer.class,Insured.class})
private String name;
#NotNull(groups={Insurer.class,Insured.class})
private String surname;
...
#NotNull(groups={Insurer.class})
private String ssn;
}
So we have a single type Person which can represent insurer and insured. The problem is that when validating Composite i want to have insurer property to be validated with Insurer group and insured with Insured. Is there anyway it can be accomplished or i need to wait for https://hibernate.onjira.com/browse/BVAL-208 resolving...
To solve your issue in a standardized way you indeed have to wait for Bean Validation 1.1 which will address BVAL-208 (group translations).
In case your Person class also has a flag or some other criteria you could use to determine whether this person is an insurer or insured you could also use a custom class level constraints. The downside is that you are loosing some of the expressiveness of annotations, since you would have to do all validation yourself in the custom constraint validator implementation.
The other alternative (again you need a way to distinguish between insurer and insured) is to use the Hibernate Validator specific GroupSequenceProvider. This way you can keep your current configuration and you just would return the right group depending on the type of Person.