Does Entity Framework 5 support unique constraints? - unique-constraint

Wondering if Entity Framework 5 supports unique constraints on entity properties? If so, how can I specify that a property should be unique?

No, it doesn't. There were plans in the past to include a unique constraint feature in EF 5.0:
http://blogs.msdn.com/b/efdesign/archive/2011/03/09/unique-constraints-in-the-entity-framework.aspx
But you can see that there is an update on top of the post:
Update: this feature has been postponed and will not be included in
Entity Framework 5.
You can vote on the feature to raise possibly the priority it gets implemented with...
http://data.uservoice.com/forums/72025-entity-framework-feature-suggestions/suggestions/1050579-unique-constraint-i-e-candidate-key-support
...because apparently it isn't even on the roadmap for EF 6.0 at the moment:
http://entityframework.codeplex.com/wikipage?title=Roadmap

Well i was looking for solution and finally i found it.
when you generate migration in code you can create unique key
CreateTable(
"dbo.TaBLE",
c => new
{
Id = c.Int(nullable: false, identity: true),
Date = c.DateTime(nullable: false),
Meter_Id = c.Int(),
})
.PrimaryKey(t => t.Id)
.Index(t => new {t.Meter_Id, t.Date}, true);
Validation before insert you can do on BLL level, so i think it can solve your problem.

While unique constraints are still not supported out of the box by EF (version 6.0 as of writing this), there are some workarounds for Code First approach to get the desired behaviour. See an attribute-based solution, as an answer to a similar question. Works with EF 5.0+.
EDIT:
Starting with EF 6.1 unique indexes are supported:
[Index(IsUnique = true)]
public string EmailAddress { get; set; }
They are the same as the unique constraints for most practical purposes.

As mentioned above it is not supported but as for now when I create a database programmatically (Code First) I use the following code in the init db section:
MainDBContext mainDBContext = new MainDBContext();
mainDBContext.Database.ExecuteSqlCommand("ALTER TABLE table_name ADD CONSTRAINT uc_FieldName UNIQUE(FieldName)");
mainDBContext.Dispose();

I found a work-around in order to achieve unique constraints on entity properties. It's really
and intuitive. Please refer to my other post:
https://stackoverflow.com/a/16496291/1873113

Related

I can't directly cast object in my Entity Framework query using ValueInjecter

I'm trying to use ValueInjecter to map my entities to my DTOs in my asp.net core project.
Could someone explain me why this works:
var list = _context.Assets
.ToList();
var vm = list
.Select(a => new ViewModel().InjectFrom(a))
.Cast<ViewModel>()
.ToList();
return vm;
But this doesn't:
var list = _context.Assets
.Select(a => new ViewModel().InjectFrom(a))
.Cast<ViewModel>()
.ToList();
return list;
Is this a ValueInjecter bug? Am I doing something wrong?
Would Automapper solve this? I strongly prefer valueinjecter syntax compared to Automapper.
Thanks for your help!
Edit:
#Chris Pratt: Thanks for your quick answer. But why would it work when I map properties manually like the example below. I'm still applying this mapping to the IQueryable interface not in-memory.
Then why this works?
var vm = _context.Assets
.Select(a => new ViewModel
{
Id = a.Id,
Code = a.Code
})
.AsNoTracking()
.ToList();
return vm;
I haven't used ValueInjector, but my guess is that it comes down to the Select being applied in-memory in the first example and to the query in the second example. Dynamic mapping is not something that can be done at the database level, and specifically, EF must be able to translate the things you pass in Select, Where, etc. into SQL. It will not be able to do so with the ValueInjector code, and hence cannot construct a query to satisfy the LINQ expression. You do not have this issue in the first example, because you pull then entities from the database first, and then you map those in-memory instances.
For what it's worth, AutoMapper would have the same problem here, so it's not technically a mapping provider problem - just one of where the operation is going to be run (i.e. in-memory vs. at the database).

Doctrine ORM "Multiple non-persisted new entities were found through the given association graph:"

$added_obj = [];
foreach ($something as $data) {
$obj = $this->class->function($data, $par2);
if (null !== $obj && !(array_key_exists
(->getVal1(), $added_obj[$obj->getVal1()] === $$obj->getVal2())) {
$this->persister->persist($obj);
$added_bank_account[$obj->getVal1()] = $obj->getVal2();
} else {
}
}
What the code does: It calls an function which returns an entity or null. If an entity was created there is an check if 2 values already exists in an array, if not, than persist and add the 2 values to an array as key/val pair.
But, when an entity is created and it already exists in the array i don't want it to be persisted, but I want to do nothing with it.
But, when I do absolutely zero with it I got the error:
```Multiple non-persisted new entities were found through the given association graph:
A new entity was found through the relationship 'MyCompany\Client\Entity\Client#something' that was not configured to cascade persist operations for entity:
which makes sense because doctrine doesn't know what to do with the created entity. How can I "destroy" the created entity so that the problem is solved.
When there is only 1 object created everything works fine.
In your case you can simply merge or clear the entity from EntityManager
ex :
$em->merge($obj);
OR
$em->clear($obj);
I was facing the same issue because it was trying to insert a duplicated registry in a particular table, when in fact I was just trying to update it.
I was doing a persist with a flush right after.
So I found that (obvious for many, but certainly helpful):
->merge
will duplicate the registry in many cases, if the id is not set properly.
If you are trying to update an entity, this is not a good idea.
->persist
In the same way, if you are trying to update an entity, you may not use it. It's used to add a new entity to the db. To update a record, you may just use flush as you can see in this example from the docs.
I had the same problem and googling this error did not give me much results, but it appeared that in case of only one entity (not multiple) doctrine gives different error message, which has a solution that worked for multiple entities too. So, let me leave here a link for it: Doctrine - A new entity was found through the relationship
This problem occurs if you got the related entity in another object manager. For example, if there was previously a check for duplication through an exception and resetting the manager.

Partial Indexes in TokuMX

We recently switched from MongoDB to TokuMX. In one collection our documents all have a numerical filed, "docType". Some documents have a field "DL_Number", and others don't. For those documents with a "DL_Number" field, the combination of "docType" and "DL_Number" should serve as a unique index.
Using C++ Legacy, we originally created an index like this:
mongo::IndexSpec().addKey("docType").addKey("DL_Number").unique().partialFilterExpression(BSON("DL_Number" << BSON("$exists" << true)));
What we were going for was an index where "docType" and "DL_Number" would provide a unique key for documents that had a field "DL_Number".
The statement worked find in MongoDB, but now that we've switched to TokuMX, the partial filter doesn't work any more. Trying to insert the second document without a "DL_Number" field throws an exception.
Has anybody else had this problem with TokuMX? Were you able to find a work-around?
Partial indexes are a MongoDB 3.2 feature, but TokuMX is based on MongoDB 3.0, so this MongoDB feature is not available with TokuMX.

Cannot make #ManyToOne relationship nullable

I have a many-to-one relationship that I want to be nullable:
#ManyToOne(optional = true)
#JoinColumn(name = "customer_id", nullable = true)
private Customer customer;
Unfortunately, JPA keeps setting the column in my database as NOT NULL. Can anyone explain this? Is there a way to make it work? Note that I use JBoss 7, JPA 2.0 with Hibernate as persistence provider and a PostgreSQL 9.1 database.
EDIT:
I found the cause of my problem. Apparently it is due to the way I defined the primary key in the referenced entity Customer:
#Entity
#Table
public class Customer {
#Id
#GeneratedValue
#Column(columnDefinition="serial")
private int id;
}
It seems that using #Column(columnDefinition="serial") for the primary key automatically sets the foreign keys referencing it to NOT NULL in the database. Is that really the expected behavior when specifying the column type as serial? Is there a workaround for enabling nullable foreign keys in this case?
Thank you in advance.
I found the solution to my problem. The way the primary key is defined in entity Customer is fine, the problem resides in the foreign key declaration. It should be declared like this:
#ManyToOne
#JoinColumn(columnDefinition="integer", name="customer_id")
private Customer customer;
Indeed, if the attribute columnDefinition="integer" is omitted the foreign key will by default be set as the source column: a not-null serial with its own sequence. That is of course not what we want as we just want the to reference the auto-incremented ID, not to create a new one.
Besides, it seems that the attribute name=customer_id is also required as I observed when performing some testing. Otherwise the foreign key column will still be set as the source column. This is a strange behavior in my opinion. Comments or additional information to clarify this are welcome!
Finally, the advantage of this solution is that the ID is generated by the database (not by JPA) and thus we do not have to worry about it when inserting data manually or through scripts which often happens in data migration or maintenance.
I came across this problem but I was able to solve it this way:
#ManyToOne
#JoinColumn(nullable = true)
private Customer customer;
Maybe the problem emerged from declaring #ManyToOne(optional = true)
That is very weird.
In JPA nullable parameter is true by default. I use this kind of configuration all the time and it works fine. If you try to save entity it should be successful.
Did you try to delete table that is created for this relationship? Maybe you have legacy table with that column?
Or maybe you should try to find solution on other chunks of code, because this is proper configuration.
Note: I have tried this configuration on PostgreSQL with JPA2 and Hibernate.
EDIT
In that case maybe you can try a little bit different definition of primary key.
For example you can use definition like this:
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column()
private Long id;
and postgresql will generate
id bigint NOT NULL
-- with constraint
CONSTRAINT some_table_pkey PRIMARY KEY (id)
If this is good enough you can try this solution.
within transaction but before the save operation, explicitly set the foreign key column value as null. By this hibernate ,never perform select queries for this foreign key related table and don't throw the exception "save the transient instance before flushing". if you want to set "null value " conditionally, then perform 1. fetch & set the value using repo call get/ find 2. then check the fetched value for the condition and set it to null accordingly .pasted the code below which is tested and found working
// Transaction Start
Optional<Customer> customerObject = customerRepository.findByCustomerId(customer.getCustomerId())
if(customerObject.isPresent())yourEnclosingEntityObject.setCustomer(customerObject)}
else {yourEnclosingEntityObject.setCustomer(null)}
yourEnclosingEntityObjectRepository.save(yourEnclosingEntityObject)
// Transaction End

UUIDs for DynamoDB?

Is it possible to get DynamoDB to automatically generate unique IDs when adding new items to a table?
I noticed the Java API mentions #DynamoDBAutoGeneratedKey so I'm assuming there's a way to get this working with PHP as well.
If so, does the application code generate these IDs or is it done on the DynamoDB side?
Good question - while conceptually possible, this seems not currently available as a DynamoDB API level feature, insofar neither CreateTable nor PutItem refer to such a functionality.
The #DynamoDBAutoGeneratedKey notation you have noticed is a Java annotation, i.e. syntactic sugar offered by the Java SDK indeed:
An annotation, in the Java computer programming language, is a special
form of syntactic metadata that can be added to Java source code.
As such #DynamoDBAutoGeneratedKey is one of the Amazon DynamoDB Annotations offered as part of the Object Persistence Model within the Java SDK's high-level API (see Using the Object Persistence Model with Amazon DynamoDB):
Marks a hash key or range key property as being auto-generated. The
Object Persistence Model will generate a random UUID when saving these
attributes. Only String properties can be marked as auto-generated
keys.
While working with dynamodb in javascript with nodejs. I use the npm module uuid to genrate unique key.
Ex:
id=uuid.v1();
refer :uuid npm
By using schema based AWS dynamodb data mapper library in Node.js, Hash key (id) will be generated automatically. Auto generated ids are based on uuid v4.
For more details, have a look on following aws package.
Data Mapper with annotation
Data Mapper package for Javascript
Sample snipet
#table('my_table')
class MyDomainClass {
#autoGeneratedHashKey()
id: string;
#rangeKey({defaultProvider: () => new Date()})
createdAt: Date;
}
The client can create a (for all intents and purposes) unique ID either by picking a long random id (DynamoDB supports 128-bit integers, for example), or by picking an ID which contains the client's IP address, CPU number, and current time - or something along these lines.
The UUID standard even includes a standard way to do this (and you have libraries in various languages to create such UUIDs on the client side), but you don't really need to use a standard.
And interesting question is how do you plan to find these items if they have random keys. Or are you planning to use a secondary index?
The 2022 answer is here:
https://dev.to/prabusah_53/aws-lambda-in-built-uuid-382f
External libraries are no longer needed.
Here is another good method taken from mkyong
http://www.mkyong.com/java/how-to-get-current-timestamps-in-java/
I adjusted his method to get the milliseconds instead of the actual date
java.util.Date date= new java.util.Date();
System.out.println(new Timestamp(date.getTime()).getTime());
The approach I'm taking is to use the current timestamp for the hash-key (or the range-key, if using a range-key too). Store the timestamp as an integer, representing the number of milliseconds since the start of the "UNIX epoch" (in the UTC timezone). Many date/time libraries can produce this number for you.
This has the advantage that if you want to have a "creation time" field in your table, your UUID already stores this information. Just call another method in your date/time library to convert the timestamp to a readable format.
(Be sure to handle the exception which will occur if a second item is created in the same table with the same millisecond timestamp; just fall back and retry the operation in that case, with a slightly later, current timestamp.)
For example:
User table
hash-key only: userID (timestamp of the creation of this user).
WidgetAttributes table
hash-key plus range-key.
hash-key: userID (use the userID from the User table of the user to whom the widget belongs).
range-key: attribID (use the timestamp of the creation of this widget-attribute).
Now you can run "query" operations on the WidgetAttributes table to get all widget-attributes for a certain user; by using "greater-than-zero" as the query-parameter for the range-key.