A Castle ActiveRecord relationship that does not use the Primary Key - castle-activerecord

I am connecting Castle ActiveRecord to a legacy database and I am having trouble wiring up a One-To-Many relationship. The problem is that the foreign key does not reference the primary key of the other table, it uses another column.
These are the tables (shortened for clarity):
CREATE TABLE [Rule](
[ID] [uniqueidentifier] NOT NULL,
[HeadingID] [int] NULL
)
CREATE TABLE [Heading](
[ID] [uniqueidentifier] NOT NULL,
[ID2] [int] NOT NULL
)
The HeadingID field in the Rule table is a foreign key which references the ID2 field in Heading.
So, in the definition of the Rule class I have:
[BelongsTo(Column = "HeadingID", PropertyRef = "OrderID")]
public virtual Heading Heading { get; set; }
This seems to work fine, I can access the Heading of a Rule with no problem (if I set the HasMany lazy of course).
In the Heading class definition I have:
[HasMany(Lazy = true)]
public IList<Rule> Rules { get; set; }
When I access the collection I get an SQL exception "Operand type clash: uniqueidentifier is incompatible with int."
It looks like AR is attempting to do a select like this (simplified for clarity):
SELECT ... FROM Rule rules0_ ... WHERE rules0_.HeadingID = ?
Where ? is the GUID from Heading.ID (it should be the int from Heading.ID2).
I can't find a property for HasMany that allows me to set the column to which the foreign key refers. Is there any way to do this?

It appears that this cannot be done. The best I could do was a custom find:
public virtual IEnumerable<Rule> Rules {
get {
return Rule.Queryable.Where(x => x.Heading == this);
}
}
This works well enough for me.

Related

Dapper Semi-Dynamic Typing?

I have a table with a similar schema:
CREATE TABLE [dbo].[Property](
[id] [uniqueidentifier] NOT NULL,
[PropertyOccupantTypeId] [uniqueidentifier] NULL,
[PropertyStatusId] [uniqueidentifier] NOT NULL
-- Other potential columns
)
It has a lot of lookup values on it that my user doesn't need to know anything about. They just need the PropertyStatus not the PropertyStatusId
Assuming the lookup tables have 2 columns each (guid: id, varchar: value) Is there a way to write a query similar to:
SELECT p.id,
po.value as OccupantType,
ps.value as PropertyStatus
-- Other potential columns
FROM Property p
join PropertyOccupantType po on p.PropertyOccupant = po.id
join PropertyStatus ps on p.PropertyStatusId = ps.id
and have that map to a Property object which looks like:
public class Property
{
public Guid id;
public string PropertyOccupant;
public string PropertyStatus;
}
Or do I need to query the additional tables manually and map the values that way?
This should work fine. Dapper doesn't care what query you write. It simply matches column names from the result set with the property names of your object.

Automatically link objects using computation on fields with Entity Framework or SQL Server

I have two "entities", Job Code and Job Family:
public class JobCode{
public int Code {get;set;}
public string Name {get;set;}
}
public class JobFamily{
public int Code {get;set;}
public string Name {get;set;}
}
JobCode.Code is a 5-digit code, and JobFamily.Code is 2 digits, which correspond with the first 2 digits of a Job Code, so there is an intrinsic relationship that I would like to capture in either the code or the database.
If I use code-first Entity Framework (or if I use database-first), is there a way to get something like:
CREATE TABLE JobFamily
(
Code int PRIMARY KEY,
Name varchar(255)
);
CREATE TABLE JobCode
(
Code int PRIMARY KEY,
Name varchar(255),
JobFamily AS (Code / 1000) FOREIGN KEY REFERENCES JobFamily(Code)
);
Is this even possible in SQL Server? I can't find anything saying it's not, but I can't find anyone trying to do it either...

Entity Framework 6 define a REALLY optional foreign key

Say I have two tables:
Products
[ProductID] PK
[Weight]
[ProductCode]
and
KnownProductCodes
[ProductCode] PK
[Description]
Now I want my Product entity to have a KnownProductCodeDetails property. BUT the interesting thing here is that Products.ProductCode may contain EITHER product codes that DO exist in the KnownProductCodes table, OR the product codes THAT DON'T EXIST in KnownProductCodes table.
So, my question is: how do I create such a relationship between the two entities in Entity Framework?
PS. By the way, is it possible for an entity to have a foreign relationship without having a corresponding constraint in the database?
Thanks!
==
Details: EF 6.1.2, Code first
Such an association wouldn't be a foreign key.
A FK is a contraint, it uses an entity's primary key values to restrict the domain of values in the referencing entity. However, you don't want the values Product.ProductCode to be constrained, so this field can't be a foreign key by definition. (Nor technically).
A second point is that meaningful primary keys, like KnownProductCodes.ProductCode, are nearly always a bad idea, because one day the business may demand to change their values. And changing primary key values is a hassle.
So the obvious thing here would be to create a real nullable foreign key to a new primary key field, KnownProductCodesId. Then you can get the display value for a product's product code either from this FK (if not null) or Product.ProductCode. And modifying KnownProductCodes.ProductCode is easy now.
Another approach could be to create a "free association". Let this be your classes:
public class Product
{
public int ProductID { get; set; }
public decimal? Weight { get; set; }
public string ProductCode { get; set; }
public virtual KnownProductCode KnownProductCode { get; set; }
}
public partial class KnownProductCode
{
public string ProductCode { get; set; }
public string Description { get; set; }
}
Now in the mappings you can define an association between them:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<KnownProductCode>().HasKey(k => k.ProductCode);
modelBuilder.Entity<Product>()
.HasOptional(p => p.KnownProductCode)
.WithMany()
.HasForeignKey(p => p.ProductCode);
}
But in the database you avoid creating the actual FK. EF will allow that, it only wants associations to point to an entity's primary key, but the association doesn't have to be a hard FK in the database.
(Note however that this takes special measures if you create the database from the model, I wouldn't recommend it).

The right way to manage database indexes with Entity Framework

I'm building my application with Entity Framework (model first principle). I'm also using MS SQL Server 2008 to store all the data of my application.
After some time of developing I have the following code:
public partial class EventInfo
{
#region Primitive Properties
public virtual int Id
{
get;
set;
}
public virtual string EventName
{
get;
set;
}
public virtual string EventKey
{
get;
set;
}
public virtual System.DateTime DateStamp
{
get;
set;
}
#endregion
}
And Visual Studio database designer have created special chunk of sql code to map this entity to the database:
-- Creating table 'EventInfoSet'
CREATE TABLE [dbo].[EventInfoSet] (
[Id] int IDENTITY(1,1) NOT NULL,
[EventName] nvarchar(max) NOT NULL,
[EventKey] nchar(32) NOT NULL,
[DateStamp] datetime NOT NULL
);
And of course, an index for Id property
-- Creating primary key on [Id] in table 'EventInfoSet'
ALTER TABLE [dbo].[EventInfoSet]
ADD CONSTRAINT [PK_EventInfoSet]
PRIMARY KEY CLUSTERED ([Id] ASC);
The EventKey is string, and actually I use it to store md5 hash (in string representation). But the thing is that my main code looks like:
int cnt = context.EventInfoSet.Where(e => e.EventKey == eventKey).Count();
and
int cnt = context.EventInfoSet.Where(e => e.EventKey == eventKey && e.DateStamp >= dateFrom && e.DateStamp < dateTo).Count();
eventKey here is a string variable. As you can see, I often deal with EventKey property. But my table could contain huge amount of records (up to 5M). And I need this code to work as fast as possible. I didn't find any option to mark EventKey as index property in designer. And I want to know:
how can I make things faster? do
I have to worry about it at all with
my code?
is there any gentle way
to force .NET development
environment generate index field
automatically?
if there is no
gentle way, and I have to update it
manually, how I can organize things
better to do it automatically?
may be you give me a link to the
article explaining all these things
with indexes, cos my knowledge lacks
here.
Thanks!
And of course, an index for Id
property
Why 'of course'? If your main access, as you yourself admit, is to count by EventKey, or EventKey and DateStamp then your best clustered key is (EventKey, DateStamp), not ID:
CREATE CLUSTERED INDEX cdx_EventInfoSet
ON [dbo].[EventInfoSet] ([EventKey], [DateStamp]);
ALTER TABLE [dbo].[EventInfoSet]
ADD CONSTRAINT [PK_EventInfoSet]
PRIMARY KEY NONCLUSTERED ([Id] ASC);
Remember, clustered key and primary key are two distinct, unrelated, concepts. You should read Designing Indexes first (including all the subtopics in the link).
Entity framework will not create index for you. Entity framework only creates skeleton of the database. If you want to tweak your database for performance (like adding indexes) you must do it at your own. After that you can switch either to database first or you can use Entity Designer Database Generation Power Pack to update your database instead of recreating it (you will need at least VS 2010 Premium).

is it safe to refactor my django models?

My model is similar to this. Is this ok or should I make the common base class abstract? What are the differcenes between this or makeing it abstract and not having an extra table? It seems odd that there is only one primary key now that I have factored stuff out.
class Input(models.Model):
details = models.CharField(max_length=1000)
user = models.ForeignKey(User)
pub_date = models.DateTimeField('date published')
rating = models.IntegerField()
def __unicode__(self):
return self.details
class Case(Input):
title = models.CharField(max_length=200)
views = models.IntegerField()
class Argument(Input):
case = models.ForeignKey(Case)
side = models.BooleanField()
is this ok to factor stuff out intpu Input? I noticed Cases and Arguments share a primary Key.
like this:
CREATE TABLE "cases_input" (
"id" integer NOT NULL PRIMARY KEY,
"details" varchar(1000) NOT NULL,
"user_id" integer NOT NULL REFERENCES "auth_user" ("id"),
"pub_date" datetime NOT NULL,
"rating" integer NOT NULL
)
;
CREATE TABLE "cases_case" (
"input_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "cases_input" ("id"),
"title" varchar(200) NOT NULL,
"views" integer NOT NULL
)
;
CREATE TABLE "cases_argument" (
"input_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "cases_input" ("id"),
"case_id" integer NOT NULL REFERENCES "cases_case" ("input_ptr_id"),
"side" bool NOT NULL
)
From: django web site
Abstract base classes are useful when you want to put some common information into a number of other models. You write your base class and put abstract=True in the Meta class. This model will then not be used to create any database table. Instead, when it is used as a base class for other models, its fields will be added to those of the child class.

Resources